I would also like to know the answer to this question. Can you use multiple OpenGLRenderer
s with a single OpenGLContext
?
From the JUCE source code, it seems that any OpenGLContext
can only have a single OpenGLRenderer
.
Yet, from @fr810’s prior suggestion in the forum:
If you have multiple components requiring opengl and you want to render all GUI components with OpenGL, then I strongly advise that you attach an OpenGLContext to the top-level component only . The top-level component can then keep track of all the subcomponents which require
renderOpenGL
callbacks and simply forward therenderOpenGL
callback to them.
Here, Fabian suggests that a top-level component attached to an OpenGLContext
could be used to keep track of multiple Components
, some of which may be OpenGLRenderer
s that have the renderOpenGL()
callback. This makes it sound like a single OpenGLContext
can be used for multiple OpenGLRenderer
s.
From what I understand, this “keeping track of subcomponents that require renderOpenGL()
callbacks” is NOT automatic since an OpenGLContext
can only be associated with a single OpenGLRenderer
. Therefore, I believe the renderOpenGL()
callbacks must then be manually called by a top-level OpenGLRenderer
attached to the OpenGLContext
.
Here is a stubbed out idea of how I believe this might work. @fr810 is this a correct interpretation of your suggestion?
/** The Top-most component of the application which we wish to be
rendered using OpenGL. It contains any JUCE Components
(or hierarchy of Components) which we wish to be rendered using
OpenGL as well as any custom OpenGL-based JUCE Components
which will render by calling lower-level OpenGL commands and using
shader programs.
*/
class TopLevelComponent : public Component,
private OpenGLRenderer
{
public:
TopLevelComponent()
: myGLComponentA (&openGLContext),
myGLComponentB (&openGLContext)
{
// Sets the OpenGL version to 3.2 and above
openGLContext.setOpenGLVersionRequired (OpenGLContext::OpenGLVersion::openGL3_2);
openGLContext.setRenderer (this);
openGLContext.attachTo (*this);
openGLContext.setContinuousRepainting (true);
// Add custom OpenGL Components
renderers.push_back (dynamic_cast<OpenGLRenderer *> (&myGLComponentA));
renderers.push_back (dynamic_cast<OpenGLRenderer *> (&myGLComponentB));
addAndMakeVisible (myGLComponentA);
addAndMakeVisible (myGLComponentB);
// Add regular JUCE Components
addAndMakeVisible (slider);
addAndMakeVisible (button);
}
~TopLevelComponent()
{
openGLContext.setContinuousRepainting (false);
openGLContext.detach();
}
void newOpenGLContextCreated() override
{
for (auto * renderer : renderers)
renderer->newOpenGLContextCreated();
}
void openGLContextClosing() override
{
for (auto * renderer : renderers)
renderer->openGLContextClosing();
}
void renderOpenGL() override
{
for (auto * renderer : renderers)
renderer->renderOpenGL();
}
private:
OpenGLContext openGLContext; // Single shared context
// Custom OpenGL Components
std::vector<OpenGLRenderer *> renderers;
MyOpenGLComponent myGLComponentA;
MyOpenGLComponent myGLComponentB;
// Normal JUCE Components (get rendered with OpenGL due to context
// attachment to this parent Component)
Slider slider;
Button button;
};
//=================================================================
/** An OpenGL-based JUCE Component that has custom OpenGL rendering.
There could by any number of different custom OpenGL-based
Components similar to this one which could all be set as
children of the TopLevelComponent and be added to the
`renderers` vector to be driven by the top level OpenGLRenderer.
*/
class MyOpenGLComponent : public Component,
public OpenGLRenderer
{
MyOpenGLComponent (OpenGLContext * externalOpenGLContext)
{
context = externalOpenGLContext;
}
void newOpenGLContextCreated() override
{
// Compile shader programs . . .
// Needs access to the OpenGLContext context member to
// constructing a OpenGLShaderProgram.
// Setup any needed OpenGL buffers . . .
// Needs access to the OpenGLContext context member to
// generate/bind buffers.
// Ex: context->extensions.glGenVertexArrays (1, &VAO);
// context->extensions.glBindVertexArray (VAO);
}
void openGLContextClosing() override
{
// Cleanup any OpenGL buffers . . .
// Needs access to the OpenGLContext context member to deallocate
// Ex: context->extensions.glDeleteVertexArrays (1, &VAO);
// context->extensions.glDeleteBuffers (1, &VBO);
}
void renderOpenGL() override
{
// Do some custom rendering . . .
// Needs access to the OpenGLContext context member for things
// like rendering scale: context->getRenderingScale()
}
private:
OpenGLContext * context;
};
I am unsure if this helps solve @YetAnotherGuy’s multi-window issue, but I was at least hoping to answer this thread’s main question for the case of a single window.