Smooth 60fps rendering

Hello, is there any way to achieve smooth 60fps rendering using JUCE’s in-built graphics? I’ve managed to achieve smooth rendering using OpenGL, however I’ve run into issues with it on Mac and would prefer to stick with JUCE’s graphics if possible.

It feels as though there is slight stuttering no matter how often I call repaint.

For context, I’m running a physics simulation using Box2D inside my plugin and drawing the objects inside the paint method.

Thanks :slight_smile:

Repaint() flags the component as dirty and that flag is picked up later, so there is always some time between calling it and it being actioned. There can also be some jitter in the timer itself. So timers and repaint() will basically never be smooth.

Look into VBlankAttachment, this is called at the frame itself, so it’s a much more reliable hook to use. Keep in mind this will be called at the rate of the display, so you can’t assume a frequency of the callback and timing will need to be managed manually and accounted for in your callback. Also be cautious of how long your executed code takes to complete, as you can overrun the frame time quite easily here.

All in all, nothing I’ve found can match going the OpenGL route, so prepare for some compromises.

1 Like

it seems to be enough to add an OpenGLRenderer to speed up the entire repainting of JUCE graphics, but I’m not sure if this is good practice

I think it depends on the platform and on what you are doing. For example, on Android simply attaching an OpenGL context has always been an enormous improvement for me, but on iOS it has usually made things worse.

The VBlankAttachment is an improvement over using a timer but I’ve found that it can can still be subject to jitter or skipped frames, and as @Fanduss said, you can’t assume a frequency. So for the best results let your painting routine measure the time elapsed from the last drawn frame and adjust accordingly. Perhaps that’s enough to get rid of the stuttering.

Hey @finneganeganegan

60fps on macOS is what I aim for with all animations / painting. It’s 100% achievable (also on non-Apple Silicon hardware).

For context, I’m running a physics simulation using Box2D inside my plugin and drawing the objects inside the paint method.

This sounds like it could be eating time. I’d recommend doing the ole “remove chunks of code” until you get back to 60fps.

Alternatively, if the same exact physics is rendering fine on open gl, it could be how you setup/use your graphics objects (like paths, etc). If you paste some example code, we might be able to help. There’s also posts sprinkled around the forum talking about common issues like too many path segments, needing to use preallocateSpace for paths, creating temporary objects each paint instead of having them as reusable members, etc…

If you want a detailed understanding on when/how/where you are making frames over ~16ms, use something like perfetto.

Edit: Oh and +1 for VBlankAttachment for anything animation-y.

Just adding: 95% of the people complaining of stutter turned out to have a problem with what they painted, not when or how often:
When you draw, have your model advance by the actual time elapsed, not by the amount you hoped your paint event would be scheduled at.
The VBlankAttachment should indeed help with that.

Thanks so much for all the tips! Attaching an OpenGLContext seems to have actually made a significant difference in my case, with everything generally drawing a lot faster. VBlankAttachment also seems to be a way better solution than using a timer.

I’ve also realized that a lot of the jitteriness would be because the physics simulation is running at a different rate to the animation. I’m going to try and see if there’s some way to interpolate / extrapolate the position of objects :slight_smile: