Animation speed

Hello,
I created a little rain animation with Xojo and I tried two methods:

  1. Draw the raindrops directly in the paint event of the canvas.
  2. Draw the raindrops to a buffer picture and then draw the buffer to the canvas.

According to older threads I read, drawing first to an off-screen picture should improve the speed of the animation. But when comparing the two methods, drawing directly to the canvas is way faster…
A usual, probably there is a mistake in my thinking. Maybe you can point me to the right direction.
The projects are here: https://cmezes.com/dl/XRain.zip

a lot depends on your intent…
I use a backing picture (or series of them) if there are parts of the image that never or rarely change
and using the Paint event to draw over that with things that DO change…

Remember using a picture object has its own overhead, as you not only have to create the picture, but you have to draw it into the canvas… doing your rain just in the Paint event removes some of that overhead…

That being said… there ARE times where using the picture method IS the way to go,

In your Rain_2_nobuffer project I get a lot of flicker (Windows).

You can fix this by simply switching the DoubleBuffer property of the canvas to ON.

[quote=337442:@Dave S]a lot depends on your intent…
Remember using a picture object has its own overhead, as you not only have to create the picture, but you have to draw it into the canvas… doing your rain just in the Paint event removes some of that overhead…

That being said… there ARE times where using the picture method IS the way to go,[/quote]

Ok, so one has to test wich method is faster depending on the situation.

[quote=337443:@Alwyn Bester]In your Rain_2_nobuffer project I get a lot of flicker (Windows).

You can fix this by simply switching the DoubleBuffer property of the canvas to ON.[/quote]

Thanks,
I will do.

Double buffer on only affects windows anyway

[quote=337440:@Christian Mézes]According to older threads I read, drawing first to an off-screen picture should improve the speed of the animation. But when comparing the two methods, drawing directly to the canvas is way faster…
A usual, probably there is a mistake in my thinking. Maybe you can point me to the right direction.
The projects are here: https://cmezes.com/dl/XRain.zip [/quote]

on macOS drawing directly in the paint event of the canvas is the fastest way and has been for a while. If you think about it; drawing to a picture and then drawing that picture to a canavs IS going to be slower than drawing directly to the canvas.

Apple also used to have CGLayers; these were stupidly fast for drawing, you could draw your rain drop into a CGLayer and then stamp that layer all over the canvas in less than a 10th of the time to draw a single rain drop image. However they decided with 10.10 to let it get buggy and then to deprecate them :frowning:

Hello,
thanks for all replies, this helped me a lot to better understand animation. In my example, when using a buffer picture, there is an overhead compared to drawing directly to the canvas. Like I said, a read in other threads, that using a buffer picture could improve animation speed, and I falsely assumed that this was a general rule. But trying the rain animation proved the opposite. So I tried to find out, in what special scenarios using a buffer picture can help improve animation speed. This seems to be the case when there are many background objects which do not move/change. Depending on the number of background objects, it can be time saving, to draw them only once into a buffer picture and then draw that picture in the paint event of the canvas. I changed the example projects accordingly to show this effect: https://cmezes.com/dl/XRain2.zip

Some more general advice when drawing as fast as you can.

  1. Don’t do any math, just draw. Use a different function to do the math and calculate where the objects should be drawn.
  2. Use #Pragma DisableBackgroundTasks to ensure that when you’re drawing, that’s all that’s happening.
  3. Avoid creating and destroying objects in the Paint event; again use a different method that’s called before the paint event.
  4. Avoid resizing images at draw time. Always try to keep then 1:1 (1 pixel is drawn into 1 pixel).
  5. If using APIs that can take floats or doubles are dimension/location parameters, ensure that you round the values to prevent misaligned pixels.

In the past I have been able to do full screen animation on a Retina MacBook Pro at over 200 fps.

I see that some API features related to CGLayer have been deprecated, but is it true CGLayer has been deprecated at all? The CGContext DrawLayerAt… methods are not marked as obsolete.

I just tested it on Sierra and it seems to work alright (no outbreak of patriotism on my side; I just translated the demo code from Multiple layers tutorial )
Only it’s not amazingly fast, at least not on Retina. If I drag the window to a low-res screen, it gives about 30 FPS.

Image Link

For example when what is drawn is complex but doesnt change very often. (not really the case for animation)
There, you draw the image to an offscreen picture only when the DATA changes.
And you paint it in the paint event, which only fires when it needs to refresh the screen.
(And in theory, only the rects that need to be updated)

That’s the problem, it used to take less than a 1,000 to draw a CGLayer and then 10.10 came along and broke it. The bug is that CGLayers are not Retina by default (like they used to be) and therefore have to have their content stretched which takes 10 times longer.

Apple’s response to my bug report was to move to CALayers instead; which are crap for drawing into a CGContext. If you let the OS draw CALayers naturally the performance is okay IMHO.

Thanks, Sam! Now I understand. Slower by a factor of ten? Wow. Yes, in my tests there was no visible difference between CGLayers and direct drawing.

A weird decision: Implementing new graphics technologies while ruining existing ones. And painting to CALayer is indeed no good substitute. Although CALayers are quite powerful and an emitterlayer would probably be the best solution for the rain simulation of the OP.

OpenGL is going through the same process right now; being replaced with Metal. Apple has never held on legacy as hard as Microsoft; but these recent annual releases don’t help.