作为一种爱好,我正在试验 OpenGL 并使用 Qt+OpenGL 编写我自己的愚蠢引擎。最后的成功是构建实体系统框架,它可以使用附加的物理引擎 (BulletPhysics) 渲染带有阴影的场景(通过渲染到纹理到 RenderBuffer)。
之后我更新到Qt 5.2,完全用Qml表达了(之前没试过)。我对 2d qml 图形进行了一些实验,并决定将 qml 用于用户界面,但拒绝 2d 项目并返回到 3d。我创建了新的 qml 项目,尝试在 qml 下渲染一些东西,如 Scene Graph - OpenGL Under QML例子。之后,我将我的旧代码从 3d 项目移到新项目,并进行了一些小的重构(应该不会影响任何东西)。
在这一刻,我厌倦了一些奇怪的错误。似乎第一帧是根据需要渲染的,但之后就出现了问题。
这是一个或多或少正常的帧(在任何移动之前)
在左上角我是输出深度缓冲区(阴影贴图)。在右上角,我用 qml 制作了一些自定义滚动条。我正在使用这个滚动条来改变阴影贴图旋转和移动相机。当滚动条居中时,没有任何移动。当我改变一些东西时,场景变得丑陋,我不知道为什么。
这是一些阴影贴图旋转后的帧
我看到阴影贴图深度缓冲区没有改变(为什么?o_0)并且场景中的阴影出错了。但是,在将我的旧代码重构为 qml 项目后,不仅影子失败了。当我移动相机时,错误变得更加奇怪。
这是将相机向下移动 (-Z) 后的帧
场景在 qml 下使用:
connect(window, &QQuickWindow::beforeRendering, this, &MyApp::renderScene, Qt::DirectConnection);
在渲染场景中:
做一些 OpenGL 传送带设置(以防止 Qml Scene Graph 的更改,可能会过多);
glViewport(0, 0, window->width(), window->height()); glClearColor(0, 0, 0, 1); glClearDepth(1); glDepthRange(0,1); glDepthFunc(GL_LEQUAL);
调用 BulletPhysics 计算物理(在测试场景中 - 两个下落的立方体)
- 将阴影贴图(仅深度)渲染到 RenderBuffer(2048x2048 纹理,GL_DEPTH_COMPONENT24)
- 将场景渲染到 RenderBuffer(两个 GL_RGBA8 纹理用于颜色和法线,一个 GL_DEPTH_COMPONENT24 用于深度)
- 渲染两个 2d 四边形 - 全屏(使用渲染缓冲区中的所有纹理渲染场景以使用阴影渲染)和侧屏(来自深度缓冲区的左上角纹理)
我厌倦了寻找正在发生的事情。 glGetError 什么都不显示。
通过 XY 轴再次移动相机一次。人的角轮廓仍然可见,并产生奇怪的效果
一些截图:
旧项目(没有 qml)
旧项目(大截图)
在新项目中,窗口大小调整也被破坏
它可以是什么?
环境:Qt Creator 3.0.0、Qt 5.2.0、Linux (Kubuntu 13.10) 64 位、HD 7750
OpenGL:在旧项目中我设置了 3.3,新项目使用 4.3(据我所知)
附言深度图是扭曲的,因为我在着色器中使用了一些额外的扭曲来改善场景中心的阴影。
最佳答案
在前几天没有得到答案的一天之后,我突然有了灵感!
我怀疑深度缓冲区有问题,并尝试输出调试用于渲染和用于渲染全屏四边形的纹理 ID。我尝试关闭渲染到纹理缓冲区交换等等。但我什至不能认为真正的问题出在 Qml 方面。
glDepthMask(GL_TRUE);//42!
其中一行类似于 42
- 回答所有问题。似乎 Qml 在第一个渲染帧之前调用 glDepthMask(GL_FALSE);
(但在发出 &QQuickWindow::beforeRendering
信号之后)。此调用的结果是,只有首先我的帧才真正通过写入深度缓冲区来渲染。为什么我认为 glDepthMask(GL_FALSE);
只被调用一次?因为在我插入“42”后 FPS 明显降低,而在我插入 glDepthMask(GL_FALSE);
用于渲染我的场景的插槽末尾后增加。
现在我可以自由旋转“太阳”(阴影)和移动相机,没有任何视觉错误。
嗨!
关于c++ - 在 Qml 场景下使用 OpenGL 渲染时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21870004/