为不同的QT小部件只获取一个QOpenGLContext

时间:2016-08-23 13:06:22

标签: c++ qt opengl qt5 openglcontext

我遇到以下问题:

我希望得到一个由许多视图组成的应用程序,它可以从不同的视角,照明和其他选项渲染一个常见的OpenGL场景。

基本上,我的问题是用qt做到这一点的最佳方法是什么?

我的第一次尝试是创建多个QOpenGLWidget并获得一个常见的QOpenGLContext,我存储了纹理,还有网格和着色器。 但它对网格不起作用,因为顶点数组对象似乎不可共享。 经过多次尝试,一个可能的解决方案是为每个需要网格的小部件存储一个VAO,但这看起来非常糟糕。

所以,我想知道是否有一个很好的替代方案来解决这类问题,或者是一个很好的文档来理解这些QOpenGLContext是如何工作的。

我想象的最简单的想法是只创建一个QOpenGLContext并在不同的小部件中使用它。但我不知道如何单独创建一个QOpenGLContext,也不知道哪种QWidgets能够显示这些渲染。

这是我的第一篇文章,所以我不知道它是否足够清楚,或者我是否需要描述我的整个架构。

2 个答案:

答案 0 :(得分:-1)

您已经尝试过,所以我传递了关于共享上下文的信息。

OpenGL上下文绑定到一个窗口:如果你只想要一个上下文,那么直接答案就是只有一个窗口。

使用窗口小部件模块,您可以在同一个QOpenGLWidget中使用多个视口来拥有同一场景的多个视图。类似的东西:

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

    //...
}

您应该设计一个视口类来存储和管理每个视口的渲染参数。

缺点是你必须检测用户点击哪个视口来处理交互:某种if event.pos.x is between 0 and this->width()/2 ...

另一种方法可能是放下小部件模块并使用Qt Quick和QML:快速窗口声明一个独特的OpenGL上下文,其中每个快速项目就像一个视口,但是封装在它自己的对象中,所以你不需要必须考虑用户在哪里进行互动。

继承QQuickItem而不是QOpenGLWidget,并使用qmlRegisterType()宏将您的类导出到QML。然后,您可以在程序中创建一个QQuickView,以在您声明项目的地方加载QML代码。 Qt的文档here中的一个例子。

答案 1 :(得分:-1)

我认为,因为多个视图/冲浪可以独立更新,不幸的是,它不可能有一个单独的QOpenGLContext来完成这项工作。并且共享上下文具有您在问题中已经指出的限制。

  

可以使用moveToThread()将QOpenGLContext移动到其他线程。   不要从与其中一个不同的线程调用makeCurrent()   QOpenGLContext对象所属的对象。上下文只能是最新的   在一个线程中,一次一个表面,一个线程只有   一次一个上下文当前。

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

因此,一种可以使其正常工作的方法是按顺序对视图进行独立更新,并使上下文逐一呈现并呈现,然后再转到下一个视图。这将保证在任何给定时间上下文仅在一个视图中是最新的。也许使用QMutex序列化更新。

或者你也可以在线程之间传递上下文并序列化它们的更新,但这是一个糟糕的方法。