Performance of an animated mask

#1

I’m pretty trash at graphics performance, and hoping to get some advice.

I’ve implemented a circular wipe between two views (full-screen Sprites). It works by masking the new view with a circular Shape, placing it on top of the old view, then tweening the mask’s scaleX and scaleY until it fills the whole screen.

It works perfectly in html5, but on native Android the framerate plummets when the mask nears the size of the screen. Oddly, the same animation in html5 running on the same Android device is silky smooth. Any ideas would be much appreciated.

Here’s the relevant code:

addChild(background);
addChild(foreground);

var mask = new Shape();
mask.graphics.beginFill(0xffffff);
mask.graphics.drawCircle(0, 0, SCREEN_HEIGHT);
mask.graphics.endFill();
mask.x = WIPE_CENTER_X;
mask.y = WIPE_CENTER_Y;
mask.scaleX = mask.scaleY = 0;
parent.addChild(mask);
foreground.mask = mask;

Actuate
    .tween(foreground.mask, Constants.WIPE_DURATION, { scaleX: 1, scaleY: 1 })
   .ease(Quad.easeOut)
   .onComplete(() -> {
       foreground.mask = null;
       parent.removeChild(mask);
   });
0 Likes

#2

Try fiddling with the cacheAsBitmap flag or using a bitmapdata (an image) instead of drawing the circle

0 Likes

#3

No dice. Tried various combinations of cacheAsBitmap on foreground, background, and mask and nothing improved performance.

I also tried var mask = new Bitmap(Assets.getBitmapData('assets/mask.png'));, but it doesn’t appear to be respecting the alpha channel, and so I just get a square mask.

I’m starting to investigate using a ShaderFilter, but setting foreground.filters = [ new ShaderFilter(maskShader) ] (where maskShader is a new Shader()) causes an exception to be thrown on render, and I don’t understand why.

0 Likes

#4

Does -Dopenfl-disable-graphics-upscaling help? (like <define name="openfl-disable-graphics-upscaling" /> in your project.xml)

0 Likes

#5

Weeeird. That breaks my animation entirely. Instead of scaling, the circle goes zooming off toward the top-left. What does that flag do?

0 Likes

#6

Hah, I guess it might have been broken. It is supposed to tell OpenFL to not upscale graphics – changing scaleX or scaleY causes OpenFL to (by default) redraw the shape. Perhaps cacheAsBitmap + cacheAsBitmapMatrix?

0 Likes

#7

I added the following lines, just before triggering the Actuate tween:

mask.cacheAsBitmapMatrix = mask.transform.concatenatedMatrix;
mask.cacheAsBitmap = true;

There’s no discernible effect on performance. =(

0 Likes

#8

More strange behaviour:
When I use cacheAsBitmapMatrix, I can’t seem to translate the circle. It renders at (0,0) in its parent container, whether I set the x/y properties or apply a matrix that includes translations. Not sure if this is related to the odd translation behaviour I see when using openfl-disable-graphics-upscaling but I figure it’s worth a mention.

0 Likes

#9

Did some investigation and logged a bug here.

0 Likes