Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为不同的QT小部件仅获取一个QOpenGLContext_C++_Qt_Opengl_Qt5_Openglcontext - Fatal编程技术网

C++ 为不同的QT小部件仅获取一个QOpenGLContext

C++ 为不同的QT小部件仅获取一个QOpenGLContext,c++,qt,opengl,qt5,openglcontext,C++,Qt,Opengl,Qt5,Openglcontext,我有以下问题: 我想得到一个由许多视图组成的应用程序,这些视图从不同的视角、照明和其他选项渲染一个常见的OpenGL场景 基本上,我的问题是用qt实现这一点的最佳方法是什么 我的第一次尝试是创建多个QOpenGLWidget并获得一个公共QOpenGLContext,在这里我存储了纹理以及网格和着色器。 但它不适用于网格,因为顶点数组对象似乎不可共享。 经过多次尝试,一个可能的解决方案是为每个需要网格的小部件存储一个VAO,但这看起来非常糟糕 因此,我想知道是否有一个很好的替代方案来解决这类问题

我有以下问题:

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

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

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

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

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


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

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

OpenGL上下文绑定到一个窗口:如果您只想要一个上下文,直接的答案是只有一个窗口

使用widgets模块,您可以在同一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

    //...
}
您可能应该设计一个viewport类来存储和管理每个视口的渲染参数

缺点是,您必须检测用户在哪个视口中单击以处理交互:某种if event.pos.x介于0和this->width/2之间

另一种方法是放下widgets模块,使用Qt-Quick和QML:快速窗口声明一个独特的OpenGL上下文,其中每个快速项就像一个视口,但封装在自己的对象中,因此您不必考虑用户在哪里交互


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

您已经尝试过了,所以我要介绍一下共享上下文

OpenGL上下文绑定到一个窗口:如果您只想要一个上下文,直接的答案是只有一个窗口

使用widgets模块,您可以在同一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

    //...
}
您可能应该设计一个viewport类来存储和管理每个视口的渲染参数

缺点是,您必须检测用户在哪个视口中单击以处理交互:某种if event.pos.x介于0和this->width/2之间

另一种方法是放下widgets模块,使用Qt-Quick和QML:快速窗口声明一个独特的OpenGL上下文,其中每个快速项就像一个视口,但封装在自己的对象中,因此您不必考虑用户在哪里交互


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

我认为由于多个视图/浏览可以独立更新,不幸的是,不可能有一个QOpenGLContext来完成这项工作。共享上下文有你在问题中已经指出的局限性

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

链接:

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


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

我认为,由于多个视图/浏览可以独立更新,不幸的是,不可能有一个QOpenGLContext来完成这项工作。共享上下文有你在问题中已经指出的局限性

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

链接:

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



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

QOpenGLContext包装OpenGL上下文。它的局限性与OpenGL上下文的工作方式有关。Qt与此无关。您需要的文档是OpenGL文档和教程,而不是QOpenGLContext文档。我知道OpenGL上下文的局限性,这就是为什么我想在整个应用程序中只使用一个,但关键是要知道如何使用qt实现这一点。QOpenGLContext包装了OpenGL上下文。它的局限性与OpenGL上下文的工作方式有关。Qt与此无关。您需要的文档是OpenGL文档和教程,而不是QOpenGLContext文档。我知道OpenGL上下文的局限性,这就是为什么我想在整个应用程序中只使用一个,但关键是要知道如何使用qt实现这一点。如果更新是连续的,使用线程的意义是什么?如果在渲染前需要完成一些cpu端的工作,那么该部分可以是并行的,只需要同步渲染。仅供参考,我使用经典的信号/插槽组合来刷新我的显示。我不知道它是否是连续的。如果两者都在同一个线程上,它就是连续的。我猜这两个都在GUI线程上,所以在这种情况下它们是顺序的。我不太适应这种多线程,但我担心维护它会带来巨大的痛苦,不是吗?如果更新是顺序的,使用线程的意义是什么?如果在渲染前需要完成一些cpu端的工作,那么该部分可以是并行的,只需要同步渲染。仅供参考,我使用经典的信号/插槽组合来刷新我的显示。我不知道它是否是连续的。如果两者都在同一个线程上,它就是连续的。我猜这两个都在GUI线程上,所以在这种情况下它们是连续的。我不太喜欢这种多线程,但是我担心它会给驴带来巨大的痛苦来维持它,不是吗?我从来没有考虑过这个解决方案,因为我认为最好不要重新发明轮子。但实际上,这可能是控制我的资源和渲染的最简单的解决方案。我想通过重新发明轮子,你可以说是多视口解决方案。你真的应该考虑使用QML解决方案:这是相同的车轮已经发明了,我看起来有点什么QT快,它看起来比旧的方法更容易使用。Netheress,在我继续我的文档步骤之前,你能告诉我qml是否允许我动态更改视口的大小或数量吗?要动态更改视口的大小,你可以看看哪个是QSplitter的qml版本。可以用按钮、信号和槽来改变视口的数量,如C++。如果您想要更复杂的布局,例如制作基于平铺的UI,也可以。我去年做了类似的东西。这有点困难,但它可以以一种干净的方式完成不幸的是,代码不是开源的,所以我不能向您展示result@Harish那是因为你不明白问题是我从来没有考虑过这个解决办法,因为我认为最好不要重新发明轮子。但实际上,这可能是控制我的资源和渲染的最简单的解决方案。我想通过重新发明轮子,你可以说是多视口解决方案。你真的应该考虑使用QML解决方案:这是相同的车轮已经发明了,我看起来有点什么QT快,它看起来比旧的方法更容易使用。Netheress,在我继续我的文档步骤之前,你能告诉我qml是否允许我动态更改视口的大小或数量吗?要动态更改视口的大小,你可以看看哪个是QSplitter的qml版本。可以用按钮、信号和槽来改变视口的数量,如C++。如果您想要更复杂的布局,例如制作基于平铺的UI,也可以。我去年做了类似的东西。这有点困难,但它可以以一种干净的方式完成不幸的是,代码不是开源的,所以我不能向您展示result@Harish那是因为你不明白这个问题是个问题