OpenGLContext rendering stutter

Hi everyone,

I decided to use OpenGL rendering for my next plugin since I know I’m going to be doing a lot of drawing with paths. So all I did was attach the editor to the OpenGLContext object. I am currently drawing two spectrum analyzers and the performance is a lot better than with the JUCE native renderer. However, I’ve noticed that the painting stutters every now and then and I don’t really know why.

Here’s a video of this happening: JUCE OpenGLContext Stutter - YouTube

The stutter is not present when rendering with the JUCE renderer, and I was wondering, if any of you have encountered this same issue? Cheers.

-Aapo

Hey @Aapo
That looks pretty :slight_smile: Nice job.

Hmm probably not the same thing, but the last time I had something similar with openGL performance it was because I had overloaded the renderOpenGL() method with too much work on each render cycle. There’s no chance of backed up requests on the message thread is there? Does openGL pick up cached data on each draw, or does openGLs refresh rate drive the recalculation of the spectrum data?

Admittedly I’m pointing out the silly mistake stuff but hopefully it might help rule out some stuff.

Jeff

Are you using JUCE from the develop branch? There were changes to the OpenGL rendering implementation as recently as yesterday, so it’s worth checking whether the problem is still present there.

Thanks for the quick response, Jeff. I’m not entirely sure what you mean, though. I’m simply calling repaint() from a timerCallback(). The repainted component then pulls audio data from a lock-free queue and goes from there. I don’t know if there’s something specific I need to take into account, though, since this is my first time instructing JUCE to render with OpenGL.

Oh, good to know. I’ll check out if the issue persists in the latest version.

Edit: Yes it does, unfortunately.

About the reply of Jeff, I think there is a common misunderstanding with the openGL-renderer.

Using the OpenGL renderer may improve the redraw performance, but it still depends on the message-thread. And if something time-consuming happens on the message thread, it will make the animation stutter (and this is very often if you are using a plug-in inside a host, which often shares the message-thread with all other plugins).

If you really want smooth animation, you can do it inside the renderOpenGL()-callback (look at the tea-pot demo), via low-level openGL commands, shaders etc…

1 Like

I’ll second the recommendation to use renderOpenGL callback. I’m using OpenGL with pixel shaders and multiple render targets, along with component rendering both over top of the OpenGL and rendered into the OpenGL render target. Everything is smooth, no jitters.

2 Likes

Thanks for the reply, Christian. That would be the best option for fast rendering. The question is, why the JUCE renderer doesn’t stutter but runs smoothly instead, even though they run on the same message thread?

Try setting only the drawing components as OpenGLAppComponent instead of attaching the editor. This won’t even need a timer, just override initialise(), shutdown() and render(), and call shutdownOpenGL(); in the destructor and repaint in the render function

Disclaimer: I’m not entirely sure that this procedure is correct or without problems. At least It works for me

Sorry, just got back. Was about to reply, then saw replies of others who worded what I wanted to say far more succintly. :slight_smile:

Hope this gets things working for you @Aapo, and thanks for the input guys!

Thanks for the input. I gave it a go but the result was the following (with a black background?):

The analyzer gets stuck there. Should I be calling some clear function after each render?

I suppose that the cleaning of the component is no longer done automatically. you will have to clean with g.fillAll

or with OpenGL in render()

juce::OpenGLHelpers::clear(juce::Colours::black);

Or with a rectangle (or several), with which you can make gradients or more elaborate backgrounds.

        juce::gl::glBegin(GL_QUADS);
        juce::gl::glColor3f(1,0,0); juce::gl::glVertex2f(-1,1);
        juce::gl::glColor3f(0,1,0); juce::gl::glVertex2f(1,1);
        juce::gl::glColor3f(0,0,1); juce::gl::glVertex2f( 1,-1);
        juce::gl::glColor3f(1,0,1); juce::gl::glVertex2f( -1,-1);
        juce::gl::glEnd();

It is also possible to generate incredibly complex backgrounds without loss of performance with the use of shaders.

Like @Marcusonic mentioned, I use

    juce::OpenGLHelpers::clear(juce::Colours);

near the top of my renderOpenGL() method. Forcing a g.fillAll surely would a need a juce repaint before each GL frame redraw which would be unnecessarily slow, no?

Thanks @Marcusonic and @splintersilk. Using the clear function got rid of the black background and freezing. However, I’m sadly still getting the stutter. I guess I’ll use the JUCE rendered for now and see if the performance is “good enough” once I have the plugin finished.

hmm thats a shame. You got rid of this though, right?

I’m still using that since it’s the only non-stuttering solution right now.

do a test, ignore the paint function. clean with a different color on render() in each pass to see possible stutter. This could at least give you a clue if the problem is in the Opengl thread or if there is some kind of overload in the drawing.

1 Like

Right, and don’t forget to set openGLContext.setContinuousRepainting(true);

As long as you are using JUCE drawing methods on moving components, OpenGL is unlikely to help you. What happens under the hood, is the OpenGL thread takes a messageManager lock and the juce drawing routine is still done on the message thread, only it’s drawn into an OpenGL frame buffer instead.

You have 2 options to improve stutter.

Shaders/vertex buffer style OpenGL drawing in the render loop. No juce drawing.

Do your expensive/time dependent juce drawing routines on another thread into an image, and in the main paint routine just draw this image.