Boris RAYMOND Boris RAYMOND - 3 months ago 29
C++ Question

Get only one QOpenGLContext for different QT widgets

I've the following problem :

I want to get an application composed of many view which render a common OpenGL scene from a different point of view, illumination, and others options.

Basically, my question is what is the best way to do that with qt ?

My first attempt was to create multiple QOpenGLWidget and get a common QOpenGLContext where I stored the textures but also the meshes and shaders.
But it didn't work for meshes because Vertex Array Objects seem to not be shareable.
After lot of tries, a possible solution is to store one VAO for each widget that need the mesh but this look really awful.

So, I wonder if there is a good alternative for this kind of problem, or maybe a good documentation to understand how these QOpenGLContext work.

The simplest idea that I've imagined is to create only one QOpenGLContext and use it in the different widgets. But I don't know how to just create a QOpenGLContext alone nor what kind of QWidgets is able to display these renderings.

It's my first post so I don't know if it's clear enough or if I need to describe my whole architecture.

Answer

You already tried, so I pass the word about shared contexts.

An OpenGL context is bound to a window: if you want only one context, the straight answer is to have only one window.

Using the widgets module, you can have multiple views of a same scene using multiple viewports in a same QOpenGLWidget. Something like:

void myWidget::paintGL() {
    //...

    glViewport(
        0, 0,
        this->width()/2, this->height()/2
    );

    // draw scene from one point of view

    glViewport(
        this->width()/2, this->height()/2,
        this->width()/2, this->height()/2
    );

    // draw scene from an other point of view

    //...
}

You should probably design a viewport class to store and manage the rendering parameters for each viewport.

The drawback is that you will have to detect in which viewport the user is clicking to handle interactions: some kind of if event.pos.x is between 0 and this->width()/2 ....


An other way could be to let down the widgets module and use Qt Quick and QML: a quick window declares a unique OpenGL context, where each quick item is like a viewport, but encapsulated in its own object so you don't have to think about where the user is interacting.

Inherit QQuickItem instead of QOpenGLWidget and export your class to QML using the qmlRegisterType() macro. You can then create a QQuickView in your program to load a QML code where you declare your items. An example from Qt's documentation here.