[Interest] Trouble rendering a single scene into multiple QOpenGLWidgets
jonathan.poncelet at talk21.com
Wed Aug 9 22:09:09 CEST 2017
I was wondering whether anyone might be able to give me any pointers regarding how to make multiple QOpenGLWidgets play nicely with a single 3D scene, as I'm fast running out of ideas.
Firstly, a little context: in my application, which is currently completely single-threaded, I have a 3D world which I want to be able to display using one or more QOpenGLWidgets. This is to be able to support UI configurations where there might be a 3D view, say, combined with some other orthographic 2D views of the same scene (a la CAD programs). Separate from the UI itself I have a rendering system which keeps track of all the geometry, shaders, textures, etc., and all the OpenGL resources required for these.
My first attempt at designing this type of application simply had the renderer make use of the current context. This was fine when I was using a single QOpenGLWidget, but fell down when I had more than one, as each widget creates and manages its own context. Things like Vertex Array Objects cannot be shared between contexts in OpenGL, so rendering in a viewport which had not created the original resources would crash the program. (To reiterate, all these contexts were on the same thread, so thread safety issues weren't part of the problem.)
I went back to the drawing board and decided on using a single context for the renderer (still on the same thread as everything else), within which all OpenGL resources would be managed. Rendering would be done to an intermediate frame buffer in this context, and the texture generated by this would be used within the target viewport's context to draw a quad and display the image. Although FBOs themselves cannot be shared, texture objects can, so in theory the QOpenGLWidget context would just need to be provided with the OpenGL ID of the texture to bind.
However, I ran into problems with this approach too. I was rendering into QOpenGLFrameBufferObjects in the first pass, and the texture I got back from the FBO in the renderer's context would not draw correctly within a QOpenGLWidget's context. When I attempted to use it, what ended up being displayed updated sporadically and with other graphical garbage, whether I used QOpenGLFrameBufferObjects or created my own pure OpenGL FBOs from scratch. This lead me to conclude that this particular method may well produce undefined behaviour, though I'm not sure why if the texture object should be shareable.
I also tried calling takeTexture(), instead of just texture(), on the Qt FBO; this did get the rendering to work as expected, but required that I discarded the texture after every frame, as the FBO would just create a new one internally. This to be seemed very wasteful, so I wasn't happy to go with it.
I've tried a great many other variants on this theme, including calling glFlush and/or glFinish, changing the context in which the FBO's texture is created, attempting to "double buffer" the textures bound to the FBO by swapping between two separate ones on each frame, etc. None of these methods have given me any success. Again, they are all in the same thread.
As a last-ditch effort, I've tried writing my own version of QOpenGLWidget, which uses a QOpenGLPaintDevice along with a QOpenGLContext that's passed in externally, in an attempt to avoid having the problem of multiple contexts. However, I'm not sure this is possible as I don't seem to have access to an OpenGL surface from within a QWidget. I know you can get a surface from a QOpenGLWindow, but deriving my application window from that would prohibit me from being able to use actual widgets on it (which I need). Embedding multiple QOpenGLWindows as widgets also seems inefficient, and doesn't solve the multiple context problem.
Is there any way at all in Qt to achieve the goal of using multiple widgets as OpenGL drawing surfaces, without requiring that each widget has its own individual context and set of resources?
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Interest