I’ve managed to improve performance of an app I’m working on greatly by simply ticking ‘Export as Bitmap’ in Adobe Animate before exporting my assets as an SWF.
I assumed this would convert the movieclip or it’s child data into Bitmap objects… but it doesn’t!
If you look, the movieclip’s contents are flattened into a bitmap, but within a single child Shape object. This shape (I’m guessing) uses a bitmapfill to display the bitmap.
At first glance, it appears I cannot therefore play with bitmap settings, like smoothing, and I’m guessing this performs less well than having a bog standard Bitmap object instead, right?
I’m thinking of writing a JSFL script which will perform a custom export. Simply it will scan the library/timeline to convert all objects with ‘Export as Bitmap’ to actual bitmaps, taking into account scaling (possibly along with a global mutiplier for greater quality control so objects can be zoomed in without loss of quality) and a global smoothing setting.
The big drawback of Bitmaps over vector data is of course the graphics become pixelated and don’t look as good when they’re scaled/rotated, especially with smoothing turned on, which got me pondering on the way OpenFl works…
I wonder if it’s possible to do something similar during runtime in OpenFl with little extra cost?
I don’t know how OpenFl renders on non-Flash platforms, but I’m assuming something like this: shapes get rendered as individual bitmaps, if they change (matrix/colortransform/filter) they are immediately redrawn before the canvas is redrawn.
What if there was something more like mipmaps? So on finalizing a shape, multiple sizes are drawn and saved into memory. If a shape is twice as big or half as small, then the relevant bitmapdata is drawn, so within 10% to 200% scaling lets say, no redrawing of the source Shape is needed.
Skewing and rotation - who cares, let the real renderer (OpenGL or whatever) deal with that when it comes to redrawing the canvas.
Perhaps this is more or less how it already works, I’m still not all that familiar with OpenFl. But then I wonder why my very simple app referred to in SWF lib performance on non-Flash targets is so laggy and choppy outside of Flash.
Our SWF exporter has an optimization that will attempt to detect simple shape symbols (which define only a rectangular bitmap fill, identical to the dimensions of the source bitmapData)
We handle this on the render side as well, so “Export as Bitmap” should result in a simpler
Bitmap-style render at runtime in OpenFL. I want to improve
shape.graphics in the future, though, to detect “low-hanging fruit” like this an do it in OpenGL instead of relying on canvas or cairo for this.
-Dopenfl-disable-graphics-upscaling which prevents redrawing of vector shapes when scaling and rotating, even if it may allow aliasing, instead performing the transform in hardware. This can help a lot with reducing redraws of software surfaces, at the risk of losing quality
Good stuff, very helpful as usual
I went ahead and wrote a custom publish script (jsfl) which converts all the objects marked as ‘Export as bitmap’ and converts them to actual bitmap symbols, also allowing for upscaling (while preserving linestyle thickness and all that) and deciding the smoothing.
I haven’t tested it extensively but it appears to work well - here’s a copy if anyone’s interested (it’s very unannotated, mind)
I’ve only tested my app on html5 and windows using actual bitmap assets, but it appears to be a bit better performance-wise than the shape w/ bitmap-fill that you get from ‘Export as Bitmap’. I haven’t done an extensive proper speed test, but at a glance it appears so. Considering you wrote most of the OpenFl framework, does it make sense that I’d see slightly better performance?
I tried exporting all my bitmaps twice the size as the source (with a 50% transform to the bitmap so it matches dimensionally obviously).
It ran excellently on the windows target, the renderer downscales bitmaps really well.
I only try html5 briefly but at a glance it appeared to do a less good job of rendering, but it could possibly be due to the html scale transform applied to the canvas. Possibly -Ddom could help here.
Side-note - is there some way to dynamically resize the stage/canvas on html5? If I resize a page I’d like the canvas to match the size of the window without stretching.
Is there some way to tell OpenFl which objects to apply this to (a displayobject property)?
Or a method which I could call to rasterize a displayobject’s children manually?
Otherwise, that’s seems a bit too broad for my purposes.
The default for HTML5 is
<window width="0" height="0" />, which should allow for
Event.RESIZE and scale to match the current window. You might want to check your project.xml, and use
if="desktop" on a
<window /> tag with an explicit size. Changing to a true bitmap might be a little faster – I guess it depends on whether the bitmap optimization in the SWF exporter is catching all of your objects or not
The “graphics upscale” define is an all-or-nothing. Perhaps
cacheAsBitmap support will help make it easier to control this on a per-object basis, though that isn’t implemented yet