简体   繁体   English

对于不同的QT小部件仅获取一个QOpenGLContext

[英]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. 我想要一个包含许多视图的应用程序,这些视图从不同的角度,照明和其他选项渲染一个通用的OpenGL场景。

Basically, my question is what is the best way to do that with qt ? 基本上,我的问题是用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. 我的第一个尝试是创建多个QOpenGLWidget并获得一个通用的QOpenGLContext,在其中存储纹理以及网格和着色器。 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. 经过大量尝试,一种可能的解决方案是为每个需要网格的小部件存储一个VAO,但这看起来确实很糟糕。

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. 因此,我想知道是否有解决此类问题的好方法,或者是了解这些QOpenGLContext如何工作的好的文档。

The simplest idea that I've imagined is to create only one QOpenGLContext and use it in the different widgets. 我想象过的最简单的想法是仅创建一个QOpenGLContext并将其在不同的小部件中使用。 But I don't know how to just create a QOpenGLContext alone nor what kind of QWidgets is able to display these renderings. 但是我不知道如何仅创建一个QOpenGLContext,也不知道哪种QWidgets可以显示这些渲染。

It's my first post so I don't know if it's clear enough or if I need to describe my whole architecture. 这是我的第一篇文章,所以我不知道是否足够清楚,或者我是否需要描述整个体系结构。

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. OpenGL上下文绑定到一个窗口:如果只需要一个上下文,直接的答案是只有一个窗口。

Using the widgets module, you can have multiple views of a same scene using multiple viewports in a same QOpenGLWidget. 使用小部件模块,您可以使用同一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 ... . 缺点是您必须检测用户单击哪个视口来处理交互:某种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. 另一种方法是放下widgets模块并使用Qt Quick和QML:一个快速窗口声明了一个唯一的OpenGL上下文,其中每个快速项都像一个视口,但封装在其自己的对象中,因此您不必考虑关于用户在哪里互动。

Inherit QQuickItem instead of QOpenGLWidget and export your class to QML using the qmlRegisterType() macro. 继承QQuickItem而不是QOpenGLWidget,并使用qmlRegisterType()宏将类导出到QML。 You can then create a QQuickView in your program to load a QML code where you declare your items. 然后,您可以在程序中创建QQuickView,以在声明项目的地方加载QML代码。 An example from Qt's documentation here . Qt文档的示例在此处

I think since multiple views/surfces can update independently, unfortunately its not possible to have one single QOpenGLContext that does the job. 我认为,由于多个视图/界面可以独立更新,因此不幸的是,不可能只有一个QOpenGLContext来完成这项工作。 And sharing contexts have the limitation you already point out in your question. 共享上下文具有您已经在问题中指出的局限性。

QOpenGLContext can be moved to a different thread with moveToThread(). 可以使用moveToThread()将QOpenGLContext移动到其他线程。 Do not call makeCurrent() from a different thread than the one to which the QOpenGLContext object belongs. 不要从与QOpenGLContext对象所属的线程不同的线程中调用makeCurrent()。 A context can only be current in one thread and against one surface at a time, and a thread only has one context current at a time. 上下文只能是一个线程中的当前电流,并且一次只能靠在一个曲面上,而一个线程一次只能有一个上下文电流。

Link : http://doc.qt.io/qt-5/qopenglcontext.html 链接: http//doc.qt.io/qt-5/qopenglcontext.html

So one way you can get it working is have independent updates to your views in a sequential order and make the context current one by one and render before moving on to the next view. 因此,使它起作用的一种方法是按顺序对视图进行独立更新,并使上下文一个一个地变得最新,并在继续下一个视图之前进行渲染。 This will guarantee that the context is current in only one view at any given time. 这将确保在任何给定时间仅在一个视图中上下文是最新的。 Perhaps use a QMutex to serialize the updates. 也许使用QMutex序列化更新。

Alternatively you can also pass the context around among threads and serialize their updates, but this is a bad approach. 另外,您也可以在线程之间传递上下文并序列化它们的更新,但这是一个不好的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM