11 Replies Latest reply: Apr 4, 2011 8:01 PM by bakedbeing RSS

    cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms

    DamonDeMers123 Community Member

      Sorry... this is a bit of a long post with some code... I'm hoping some of the more experienced flash/iphone developers can help clarify a few things for me...

       

      I'm a beginner AS3 developer; I've combed over the Adobe literature and the various threads in this forum and I'm still having trouble understanding when best to use cacheAsBitmap and cacheAsBitmapMatrix.

       

      In simple terms, it appears that:

       

       

      1.

      mySprite.cacheAsbitmap = true;

       

      Use for vectors graphics in order to cache them.  This is easier on the device because the GPU can animate the bitmap much faster than the CPU can redraw the vector.  Works for simple X and Y transitions (move an object across the screen).

      (From Packager for iPhone Dev Guide: Setting cacheAsBitmap to true alone causes a display object (and any children) to be cached. The display object is not redrawn when new regions are exposed, or the whole combined graphic is translated.)

       

       

       

      2.

      matrix:Matrix = new Matrix();

      mySprite.cacheAsBitmapMatrix = matrix;

      mySprite.cacheAsBitmap = true;

       

      Use the cacheAsBitmapMatrix property when you plan to scale or rotate the vector graphic.

       

      (From Packager for iPhone Dev Guide: For display objects that have cacheAsBitmap set to true, setting cacheAsBitmapMatrix causes the GPU to use the bitmap that results from the matrix transformation. The GPU uses the bitmap representation even if the object is rotated or scaled. The GPU can composite and animate this bitmap much more quickly than the CPU can redraw a vector-rendered object.)

       

       

       

      3.

      Existing bitmap images used in the project are pre-cached.

       

      (From JMP808 on this thread:  http://forums.adobe.com/message/3244008#3244008:

      CacheAsBitmap puts a bitmap version of display objects onto the GPU. Bitmaps are already pre-cached, so you only need to call cacheAsBitmap on items with vector components (eg if you do a graphics.drawCircle for instance, or you've drawn your character with the shape tools, as opposed to importing a JPG/PNG)

       

       

      once the item is on the GPU (as a texture basically) the hardware can move the item around the screen quickly without reverting to the software renderer (which is slower). If you make any modifications to this cached item then it will need to go back to the software renderer. (Note however if you use cacheAsBitmapMatrix you can also use the hardware to scale, rotate and alpha the cached bitmap)

       

       

       

       

      So in very simple terms it would seem that you could want to use the cacheAsBitmap property to vectors you planned to move around the screen but maintain proportions, cacheAsBitmap + cacheAsBitmapMatrix to vectors you wanted to scale, rotate, alpha and then, finally, completely avoid the process for png/jpg or other bitmap images because they are pre-cached.

       

      Am I totally missing something?  Oversimplifying? (most likely).

        • 1. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
          DamonDeMers123 Community Member

          I also wanted to provide an example of how my understanding above must be incomplete...

           

           

          My project uses a bunch of PNG files converted to Movieclips which are imported and placed on the screen using actionscript.  No vector images...just PNG converted to movieclips then exported for actionscript.

           

          I was having trouble scaling a movieclip across the stage over a background image.  The scale transition was very choppy.  The basic code looks something like this.

           

           

          Attempt 1: 

           

          Results = Very Choppy Tween on iPad

           

           

           

          public function CacheTestAS()

           

          {

          //Background image

           

          _i505 = new i505;

           

          addChild(_i505);

           

           

          //Image that sits on top of background that I intend to scale

           

          _grid = new Grid;

           

          addChild(_grid);

           

          // Listen for click event to scale Grid

           

          _grid.addEventListener(MouseEvent.CLICK, moveGrid)

           

           

          // Scale Grid Using TweenLite

           

          function moveGrid(e:MouseEvent):void

          {

          TweenLite.to(_grid, 4, {scaleX:0.3, scaleY:0.3});

          }

           

           

          }

           

           

           

           

           

          Notes:  I figured that because I was scaling a movieclip it might help to apply the cacheAsBitmapMatrix to the _grid.  It didn't solve the problem.  See next example.

           

           

           

          ~~~~~

           

           

           

           

          Attempt 2:

           

          Results = Very Choppy Tween on iPad (additions highlighted in orange)

           

           

          public function CacheTestAS()

          {

          //Background image

           

          _i505 = new i505;

           

          addChild(_i505);

           

           

          //Image that sits on top of background that I intend to scale

           

          _grid = new Grid;

           

          var _myMatrix:Matrix = new Matrix();

          _grid.cacheAsBitmapMatrix = _myMatrix;

          _grid.cacheAsBitmap = true;

           

           

          addChild(_grid);

           

          // Listen for click event to scale Grid

           

          _grid.addEventListener(MouseEvent.CLICK, moveGrid)

           

           

          // Scale Grid Using TweenLite

           

          function moveGrid(e:MouseEvent):void

          {

          TweenLite.to(_grid, 4, {scaleX:0.3, scaleY:0.3});

          }

           

           

          }

           

           

           

          Notes:  Adding the cacheAsBitmapMatrix alone didn't help.  So finally I tried to cache the background image (_i505 in these examples) because I read somewhere (on this forum) that if the background image isn't cached then any image you move over it will need to be recalculated.... this didn't seem to make sense to me because from what I've read, any bitmap images should be pre-cached and the background image itself wasn't changing.

           

           

          ~~~~

           

          Final Attempt:

           

          Results = Tween is Smooth as Butter on iPad (additions highlighted in blue)


           

           

          public function CacheTestAS()

          {

          //Background image

           

          _i505 = new i505;

          _i505.cacheAsBitmap = true;

           

          addChild(_i505);

           

           

          //Image that sits on top of background that I intend to scale

           

          _grid = new Grid;

           

          var _myMatrix:Matrix = new Matrix();

          _grid.cacheAsBitmapMatrix = _myMatrix;

          _grid.cacheAsBitmap = true;

           

           

          addChild(_grid);

           

          // Listen for click event to scale Grid

           

          _grid.addEventListener(MouseEvent.CLICK, moveGrid)

           

           

          // Scale Grid Using TweenLite

           

          function moveGrid(e:MouseEvent):void

          {

          TweenLite.to(_grid, 4, {scaleX:0.3, scaleY:0.3});

          }

           

           

          }

           

           

           

          Notes:  This seemed to work great.  Simply applying the cacheAsBitmap to the background image made all the difference.  If I removed _myMatrix from the _grid it was back to the 'ole choppy/stutter tween... so *both* of these chunks of code needed to be in place for the tween to render smoothly on the iPad.

          • 2. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
            Breezzze1-pRmaHp Community Member

            Great sharing.

             

            I'm still confused about my scenario: I want to rotate/scale/alpha a sprite which contains several bitmaps that are changing their BitmapData, do I need to set cacheAsBitmapMatrix for each of the individual bitmaps, cos they are being transformed by their parent sprite?

             

            Thanks in advance.

            • 3. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
              Applauz78 Community Member

              This is very interesting...

               

              What if there are other elements on the screen that are above the image that is being tweened ?  ie/ buttons, nav bar, etc.

               

              Do items that are above the image being tweened also need to be cached ?

              • 4. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                DamonDeMers123 Community Member

                I'm not entirely sure if items above the one being tweened need to be cached... but I found it peculiar that the tween would not render smoothly until the backdrop image was cached.  (The backdrop image is rather large btw... 1024 by 768... sized specifically for the iPad). 

                 

                I noticed that when *just* smaller images where behind the tweened image it seemed to be able to render smoothly... so the size/dimensions of the backdrop image/s is relevant.

                 

                I'd still love to hear from someone here the quick and dirty on best practices for cacheAsBitmap and cacheAsBitmapMatrix.

                • 5. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                  spazzblaster Community Member

                  I don't understand why anything you did would have worked if cacheAsBitmap and cacheAsBitmapMatix is only for vector graphics.  Aside from one other post, everything I read, including earlier in your own post, said you shouldn't need to bother caching bitmaps.  Just wondering if you had any idea why it improved your results?

                  • 6. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                    kglad CommunityMVP

                    what the op calls an image (_505) isn't really an image (bitmap).

                    • 7. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                      michelangelo.capraro Community Member

                      i'm guessing, but based on my experience, in the last version of the PFI cancheAsBitmap really boosted perfomance a ton, even on bitmaps. in AIR 2.6, cacheAsBitmap seems to do the opposite.

                      • 8. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                        Colin Holgate CommunityMVP

                        Here's how to think of when to use the cacheAsBitmap and cacheAsBitmapMatrix:

                         

                        Only bitmaps can be cached. Therefore, you must be at least doing a cacheAsBitmap on vectors if you want them to be handled by the GPU.

                         

                        Anything that needs to be scaled or rotated needs its bitmap to be cached along with a matrix for the GPU to process.

                         

                        Setting the matrix requires that the item gets cached based on that matrix.

                         

                        Clearly you need to do both in order to rotate vectors with the GPU (by which time they are bitmaps anyway), but less obvious, when you set the matrix the item will get recached based on that matrix, and that would apply to bitmaps too. So you do need to cacheAsBitmap bitmaps to get them to recache, if you happen to be doing a cacheAsBitmapMatrix in order to have the GPU rotate and scale them.

                         

                        One useful thing to know, if you have manually set a movieclip containing a bitmap to cacheAsBitmap on the stage, you can then just set its cacheAsBitmapMatrix in the constructor of a class for that symbol. No need to cacheAsBitmap again, because it hasn't yet cached.

                         

                        About the need to also cache the background, one time when that may be needed is if you are using a 480x320 stage on an iPad (where it will show as 1024x768 and reveal more content above and below the stage), I suspect that in this case the background image is scaled to 2.13333, and so if it doesn't have a matrix to explain that, then every time something in front of it gets moved, the affected rectangle has to be sent to the GPU again. I know that when I set a matrix for those background, the foreground items do animate a lot better.

                        • 9. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                          michelangelo.capraro Community Member

                          colin: do you see any lag as described here when even caching one background bitmap?

                          • 10. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                            Colin Holgate CommunityMVP

                            The most lag I've seen is with using a set of six bitmap slices that totaled over 2100 pixels tall, and that would clear itself if I restart the iPad. It would be nice if the AIR 2.6 improvements means that you can get good performance on bitmap that are static, and we can avoid using up GPU memory just to make things smooth.

                            • 11. Re: cacheAsBitmap & cacheAsBitmapMatrix in Layman's Terms
                              bakedbeing

                              I think part of the problem here is you might be going the long way around, creating and then fixing a problem. It sounds like you're taking a single image, putting it in a movieclip, exporting it as type flash.display.MovieClip, and then asking Flash to convert that bitmap-upgraded-to-a-movieclip back to a bitmap, which is something it wouldn't assume on it's own.

                               

                              If you only need the image and no MovieClip functionality, export the image directly from the library (it will export as flash.display.BitmapData) and then create it as a typed bitmap like follows:

                               

                              var myLibraryBitmap:Bitmap = new Bitmap(new LibraryBitmapSymbol());

                               

                              Nothing to cache as Bitmap, also no memory overhead of your movieclip + it's cached cousin.