我正在创建一个应用程序,它通过QOpenGL*类与 OpenGL 交互。图形通过放置在 UI 表单中的QOpenGLWidget显示。
现在,有一个用于 CAD 的库(Open CASCADE),它的 OpenGL 接口需要渲染窗口的句柄。问题是:我可以以某种方式说库将所有内容呈现给提到的小部件吗?
换句话说,有没有办法将小部件解释为本地的,可能是特定于平台的(此处为 HWND)窗口,以便库准确地在那里呈现自己的东西?
谢谢
我正在创建一个应用程序,它通过QOpenGL*类与 OpenGL 交互。图形通过放置在 UI 表单中的QOpenGLWidget显示。
现在,有一个用于 CAD 的库(Open CASCADE),它的 OpenGL 接口需要渲染窗口的句柄。问题是:我可以以某种方式说库将所有内容呈现给提到的小部件吗?
换句话说,有没有办法将小部件解释为本地的,可能是特定于平台的(此处为 HWND)窗口,以便库准确地在那里呈现自己的东西?
谢谢
QOpenGLWidget与QGLWidget不同。
嵌入 OCCT 3D 查看器的经典方法(您可以在 OCCT 随附的 Qt IESample 中找到)创建具有唯一窗口句柄标志的 QWidget,获取此窗口句柄并要求 OCCT 处理此窗口的 OpenGL 上下文创建。这是最直接、健壮和可移植的方式,但有一个限制 - Qt 将无法在此 QWidget 之上绘制半透明小部件。这不是 OCCT 的限制,而是 Qt Widgets 设计的限制。
QOpenGLWidget旨在通过允许混合自定义 OpenGL 渲染和普通小部件来解决此限制。然而,外部 OpenGL 图形引擎的集成变得更加复杂和脆弱。从 QOpenGLWidget 窃取 winId() 并不是很有帮助,因为渲染内容预计不会被绘制到窗口本身,而是被绘制到由 QOpenGLWidget 创建的 OpenGL 帧缓冲区对象 (FBO) - 请参阅QOpenGLWidget::defaultFramebufferObject()属性。
外部渲染器应该渲染到这个 FBO 中,以便正确组合 Qt 小部件。幸运的是,OCCT 足够灵活,可以进行这种集成。不幸的是,这种集成需要一些 OpenGL 知识,以及 Qt 和 OCCT 的使用。为此,您需要询问已由 Qt 创建的 OCCT 包装 OpenGL 上下文(因为V3d_View::SetWindow()提供了一个Aspect_RenderingContext类型的可选参数,它对应于 Windows 上的HGLRC,并且可以在渲染线程中使用wglGetCurrentContext()获取)以及由 QOpenGLWidget 创建的 FBO(为此,OCCT 提供了OpenGl_FrameBuffer::InitWrapper()和OpenGl_Context::SetDefaultFrameBuffer()方法,以及OpenGl_Caps::buffersNoSwap标志将窗口缓冲区交换管理留给 Qt)。
OCCT 尚未附带使用QOpenGLWidget的示例,但您也可以找到qt/AndroidQt示例,该示例实现了将 OCCT 3D 查看器嵌入到QtQuick应用程序中的类似内容。
经过一番调查,我发现方法QOpenGLWidget::winId()返回了正确的句柄。现在才发现,因为渲染出来的场景马上就消失了,只剩下黑色的画面。但是,当调整视口大小时,场景会返回(但会再次消失)。看起来 Open CASCADE 在 Qt 5 OpenGL 实现方面存在问题,因为据我所知,QGLWidget 没有这样的问题。