2

我有以下问题:

我想获得一个由许多视图组成的应用程序,这些视图从不同的角度、照明和其他选项渲染一个常见的 OpenGL 场景。

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

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

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

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

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

4

2 回答 2

-1

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

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

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

因此,您可以让它工作的一种方法是按顺序对您的视图进行独立更新,并一个一个地使上下文成为当前的并在移动到下一个视图之前渲染。这将保证上下文在任何给定时间仅在一个视图中是当前的。也许使用 QMutex 来序列化更新。

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

于 2016-08-23T14:22:23.217 回答
-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 文档中的一个示例。

于 2016-08-23T14:02:21.587 回答