OpenGLRenderer without a Component (complete offscreen render for Spout/Syphon)

opengl

#1

Hello,
i’m struggling with OpenGL usage in JUCE.
I’ve managed to create a functional Component that is an OpenGLRenderer and has its own openGLContext, and draws into an image during it’s renderOpenGL call and then send it via Spout
But this component actually needs to be visible and showing, with a non-zero size, otherwise the renderOpenGL function is never called.
So basically, with this technique you can only use OpenGL on visible components ?
What’s strange is that when i set the renderer to this object and i attach the context to it as well, the object becomes invisible, but the mouse interaction seems to work since i can’t click on objects behind this one (edit: this behavior is true when i also set the mainWindow as an OpenGLRenderer and attach a context to it)

What i want to achieve is actually quite simple : i would like to be able to have a separate openGLContext and be able to draw some graphics in a texture without needing to show it on screen, just into a texture that i’ll send over Spout or Syphon later.

Do you have any clues for that ?

Thanks


#2

Yes this is true.

I would suggest to attach your top-level component to an OpenGLContext (see for example here). Then everything in that window will be rendered with OpenGL (which is faster anyway). Then, also attach an OpenGLRenderer to this contect and use it to render to a separate framebuffer.


#3

Thanks a lot for this, i managed to get it working with you help.

What’s odd in this case is that i don’t really want my main component to have “continuousRepainting” enabled in it’s attached openGLContext, but if i don’t activate it, obviously i can’t render at 60fps my offscreen texture… it seems that the continuousRepainting option is taking some hit on the CPU so i don’t know if it’s the best solution.
But as it is the only one that works for me, let’s keep it that way, i have other GL problems that i’ll put in another topic.

Thanks again, and if you want to check the code, or even use it / improve it, i’ll be updating this repo with it (i’m now working on the Spout receiver) :


#4

I’ve got a bit further in my tests, and got to check almost every topic related to OpenGL drawing in the forum, but i can’t find a final answer, so i’ve few more questions :

  • Looking at the OpenGLContext source code, it seems actually impossible to do anything with a context without attaching it to a component ? My question is : is it difficult or just impossible ?

  • When using the technique above (using only one context and dispatch the openGLRender in my other classes), when i try to use the image.getPixelAt() on a image created with OpenGLImageType, this mess up the whole rendering : all my components are not rendered anymore, and i can’t draw anything after this call. If i create another Image (non-GL) and draw the GL image into this one, then i can access the getPixelAt function on that later image and everything works fine. But as i have to do that at each renderGL() call, when dealing with 1920x1080 textures, everything gets reaaally slow.

  • When profiling from VS the CPU activity, there is a strong CPU activity on the deactivateCurrentContext() function (almost 100% of one my CPUs), even when i don’t copy the GL image to a CPU image.

Any suggestion is welcome !
Thank you


#5

I also had severe performance issues related to this; I am not sure if the CPU usage was very high, the main problem was that the GUI responsiveness decreased dramatically. I fixed it in the end by calling:

openGLContext.setComponentPaintingEnabled(false);
openGLContext.setContinuousRepainting(false);

in the component’s constructor. I believe that the combination of continuous repainting and component painting was locking the MessageManager for long periods of time.

Not sure if your issue is related to that, I hope the comments are somewhat useful.

Edit: all in all, I would suggest that you use OpenGL functions directly, rather than relying on the Juce constructs around them, since you will find much more documentation about plain OpenGL. I only use the OpenGLAppComponent to get the Window and context created for me without having to rely on OS specific APIS :slight_smile:


#6

Even in continuous re-paint mode, it really shouldn’t be using that much CPU - at least in release mode. One issue is that there are a lot of tight loops in the OpenGL code which have poor performance in debug mode but should be more or less fine in release mode.

As I said above, you need to attach an OpenGLContext to a component in order for it do to anything. Attaching it to the top-level component will increase render speeds (in release mode) of normal JUCE components on Linux/Android/Windows (on macOS/iOS CoreGraphics is faster), so I recommended this approach. But you can attach it to any component you like.


#7

Thank you for those replies,
i will test the different combinations, one thing i still don’t understand now is if it’s possible to have mutiple OpenGLContexts, or juste be able to draw GL in different components. I’ll try to make myself clear with my use-case :

  • I got an openGLContext attached to my mainComponent, and the glRender is then dispatched to differents classes, one using the glRender function to generate a spout/syphon texture (complete offscreen), and i’ve got a lite of visible components where i want to show a 3d model, each one having it’s own rotation, lighting and view.
    If i try with the setup above (one openGLContext dispatching to everyone), the function gets called but i can’t see anything rendering.
    if i try with one openGLContext per component, i can’t see anything still AND when deleting them, it messes up the whole rendering windows.

You can see the code here (largely copied from examples, but i may have made some mistakes when adapting) :


Thanks