OpenGL - Multiple Calls to Visibility/Rendering Methods Causes Black Rendering Output

I have a custom OpenGL-based juce::Component that is a juce::OpenGLRenderer and has its own juce::OpenGLContext. This Component uses custom OpenGL shader programs and is able to successfully render using an OpenGL render thread.

To initiate rendering I call:

myOpenGLComponent->setVisible (true);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (true);

Everything is all well and good, rendering and resizing properly, until I call either of the above methods again, any number of times, either setting them to true or false.

After calling these methods again, and setting them to be true, I would expect to see my component properly rendering again, but instead the GL portion of my component renders as black. The pure JUCE Component’s contained within myOpenGLComponent still render properly, but the custom OpenGL shader program renders as black. In the debugger, the renderOpenGL() callback of my OpenGLRenderer is still being called properly by the OpenGL rendering thread. Initially inspecting some of the variables during rendering, I did not find any NULL objects.

Has anybody had a problem like this with a custom OpenGL-based Component?
I would like to be able to show and hide my OpenGL component as I please.

Note: I am using multiple OpenGLContexts in my JUCE app for different OpenGL components. Maybe this is contributing to the issue?

No answer to your main question, but I’d advise against that and instead use one context for the whole GL rendering work and make use of the glViewport to render to the desired sub-area as you already asked for in a previous thread. The reason behind that is that on least on Windows you’ll see a massive performance drop when running multiple OpenGLContexts from within a single process. Just a friendly heads-up before you start designing something more complex and run into this later :slight_smile:

Regarding your main question, are you really only calling these functions or do you anything else that alters the state of your component? Especially when working with transforms and viewports I managed to render my content somewhere offscreen more then once by some miscalculation :grimacing: Maybe you should not only inspect variables for null pointers but also check if there are no other miscalculations. Maybe you want to share a minimal code example that reproduces your issue?

1 Like

Yeah, on Mac OS X, i had a freeze crash on OpenGL buffer swap using multiple contexts. Best to only have one and add polygons to that when needed. It’ll also be much, much faster. Also, turn off Vsync.

1 Like

Mhm, I wouldn’t give this as a general advice, this can speed up things, but depending on what kind of content you are drawing, this can also make your drawing look a lot worse. Definitively an option to play around with at some point, but I personally would start with vsync being enabled as default

Vsync waits are a bad thing here in my experience with Juce. Some hosts , like Cubase, don’t like plugins doing things like that. They used be OK, but not now. I usually resort to rendering on a timer, but not at 60 frames a second.

@DaveH @PluginPenguin Thank you both for your replies and useful information!

I will move to a single OpenGLContext due to the issues you all mention. When using a single context, do either of you two use the context to render both regular painted JUCE Components and custom OpenGL-based components? My goal is to render a few custom OpenGL-based components and many regular JUCE components using a single OpenGLContext. Is this possible?

Regarding this thread’s main question of visibility:

Yes, when I run the following code

myOpenGLComponent->setVisible (true);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (true);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (false);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (true);

it shows up as black, but if I only run:

myOpenGLComponent->setVisible (true);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (true);

it shows up fine.

I am gonna try to dig into my code more to find the problem. I have written OpenGL Components before that do not exhibit this behavior, so it must be some code I have written causing this. Just wondering if anyone had run into this kind of behavior before and knew a likely cause.

I found the issue with my code that caused this problem!

Calling either of the methods I have referenced above with a visibility argument, bool shouldBeVisible,

myOpenGLComponent->setVisible (shouldBeVisible);
myOpenGLComponent->getOpenGLContext().setContinuousRepainting (shouldBeVisible);

causes a callback to be made to OpenGLRenderer::newOpenGLContextCreated() if shouldBeVisible is set to true, and a callback to be made to OpenGLRenderer::openGLContextClosing() if shouldBeVisible is set to false.

I was unaware that showing/hiding a OpenGLRenderer Component causes these callbacks to be made, as I assumed these callbacks were only made when attaching or detaching the OpenGLContext.

Because of my unawareness, I was not doing proper uniform refreshing in my OpenGLRenderer::newOpenGLContextCreated() method, thus the color uniforms I needed to set for rendering the color of my visualization were not being set, and defaulted to black. This caused my visualization to render as black while still properly showing the overlaid JUCE components.

Essentially, I need to code with the assumption that OpenGLRenderer::newOpenGLContextCreated() is called every time my component is shown and OpenGLRenderer::openGLContextClosing() is called every time my component is hidden.

Thanks all for the comments and help.

1 Like