7

我正在混合使用 OpenGL 的两个库:Qt 和 OpenSceneGraph。我的目标是 OpenGL ES 2,所以一切都是通过着色器和 ES 2 兼容调用完成的。

通过尝试将 OSG 绘制到 QDeclarativeItem 上,我专门将 OSG 与 QtDeclarative 一起使用。我按照 Qt 文档中建议的方式执行此操作:在 beginNativePainting()/endNativePainting() 之间包装所有 OpenGL 调用。

这工作正常,直到我在我的 OpenSceneGraph 场景中使用纹理。当我这样做时,我的 QML 窗口会因为没有更好的词而“混乱”。为了使其尽可能简单,我的 OSG 场景由一个应用了纹理的平面组成。我使用基本的 OpenGL 调用重新创建了场景,并且不再出现问题。这里的问题总结为一堆图片:

  • QtDeclarative 引擎使用 OpenGL 来绘制东西。我设置了一个简单的 QML 页面:

在此处输入图像描述

  • 我直接使用 OpenGL 创建了一个简单的场景。这是一架飞机,上面涂有纹理。

在此处输入图像描述

  • 现在我尝试在 OSG 中设置相同的场景......相同的着色器等。

在此处输入图像描述

您可以看到最后一个屏幕截图发生了一些奇怪的事情。不用担心原始 OpenGL 场景是透明的黑色背景,这只是 OSG 使用黑色透明色。问题是使用 QML(矩形)设置的其他项目搞砸了。

编辑:澄清发生了什么:我用 QML 绘制的矩形都延伸到屏幕的右边缘。我还注意到,如果我在 QML 中的 OpenSceneGraph 项目之后绘制矩形,它们不会出现(我之前没有注意到这一点)。我在以下屏幕截图中的 OSG 项目之后绘制了紫色黑色矩形......请注意它消失了。可能会发生更多奇怪的事情,但这是我观察到的所有玩矩形的东西。

在此处输入图像描述

在此处输入图像描述

我对 OpenGL 还很陌生,所以我不知道什么样的调用/状态设置会导致这样的事情发生。我认为 OpenSceneGraph 会进行一些 OpenGL 状态更改,这会扰乱 Qt 的绘图引擎。我也知道这只发生在 OSG 使用纹理时……如果我不在我的 OSG 场景中应用纹理,这不会发生。这就是我卡住的地方。

此外,我尝试使用 BuGLe 来获取在 OSG 中启用和不启用纹理的 OpenGL 调用跟踪,以查看是否可以找出有问题的状态更改。我发现了一些差异,甚至是 OSG 在两者之间更改的一些全局状态(例如 glPixelStorei()),但是重置我发现的更改没有任何区别。如果我知道要寻找什么,那将有很大帮助。如果有人感到疯狂,我也有堆栈跟踪:

编辑2: 这是一个可能有用的差异。在相关行明显之前,您需要向下滚动。 http://www.mergely.com/nUEePufa/

编辑3: 哇!好的,那个差异帮助了我很多。OSG 启用 VertexAttribArray 3 但不会禁用它。在 OSG 渲染其帧之后调用 glDisableVertexAttribArray(3) 似乎部分解决了问题;不再有 QML 矩形的拉伸。但是,在 OSG 项目之后绘制的矩形仍然不显示

4

2 回答 2

2

在对跟踪日志着迷之后,我想我发现了两个需要重置的 OpenGL 东西,然后才能将控制权传回 Qt 以导致上述问题消失。我在编辑中提到了一个......我将在这个答案中总结两者。

矩形/QML 项目失真

QPainter 直接将顶点属性 3、4 和 5 用于看起来与这些矩形的几何形状相关的东西。这可以在跟踪中看到:

[INFO] trace.call: glVertexAttrib3fv(3, 0x2d94a14 -> { 0.00195312, 0, 0 })
[INFO] trace.call: glVertexAttrib3fv(4, 0x2d94a20 -> { 0, -0.00333333, 0 })
[INFO] trace.call: glVertexAttrib3fv(5, 0x2d94a2c -> { 0.2, 0.4, 1 })

禁用相应的顶点属性数组可修复弹性矩形问题:

 glDisableVertexAttribArray(3);
 glDisableVertexAttribArray(4);
 glDisableVertexAttribArray(5);

在 OSG 项目之后绘制的项目不呈现

回想起来,这很容易,与纹理没有任何关系。在尝试向我的场景添加纹理之前我没有注意到这一点,所以混合这两个问题是我的错。我还搞砸了我发布的痕迹和差异;在我发现订购问题后,我从未更新它们以解决订购问题(对不起!)

无论如何,QPainter 希望关闭深度测试。当您调用 beginNativePainting() 时,Qt 将关闭深度测试,并且当它开始绘制其项目时……但您应该在交回控制权时将其关闭:

  1. QPainter 绘制东西(DEPTH_TEST = off)
  2. OSG 绘制东西(DEPTH_TEST = on)
  3. QPainter 绘制更多东西 [期望 DEPTH_TEST = off]

正确的跟踪日志显示我没有这样做......所以修复是

glDisable(GL_DEPTH_TEST)
于 2012-07-09T06:35:34.933 回答
1

也许您只需要重新启用 GL_TEXTURE_2D?我在您的示例中注意到 OSG 启用并随后禁用 GL_TEXTURE_2D 的纹理。因此,您的两种情况(有纹理与无纹理)之间的区别在于,使用纹理的情况在禁用纹理的情况下完成,而没有纹理的情况则使 GL_TEXTURE_2D 处于初始状态。

如果 Qt 需要/期望启用纹理来绘制四边形,则可能不会显示任何内容。

于 2012-07-09T05:40:56.597 回答