[Interest] Trouble rendering a single scene into multiple QOpenGLWidgets

Sean Harmer sean.harmer at kdab.com
Thu Aug 17 11:38:54 CEST 2017


Hi,

your second approach of rendering into an FBO and using those textures in 
multiple QOpenGLWidgets should work if:

1) You enable Qt::AA_ShareOpenGLContexts via QCoreApplication::setAtribute() 
before you create the application object.

2) Your own context is a sharing context with one of the QOpenGLWidget's 
context.

That way the texture object resources can be shared. You may still need to 
make use of fences or other mechanisms to synchronise when it's safe to render 
with the textures your context is rendering to.

Alternatively with just 1) above, you can share textures, vbos etc between all 
the widgets and then you just need to replicate the unshared resources such as 
VAOs.

Cheers,

Sean

On Wednesday, 9 August 2017 21:09:09 BST Jonathan Poncelet wrote:
> Hello all,
> 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? Thanks,
> Jonathan Poncelet


-- 
Dr Sean Harmer | sean.harmer at kdab.com | Managing Director UK
KDAB (UK) Ltd, a KDAB Group company
Tel. +44 (0)1625 809908; Sweden (HQ) +46-563-540090
Mobile: +44 (0)7545 140604
KDAB - Qt Experts



More information about the Interest mailing list