在 Qml 场景下使用 OpenGL 渲染时出现奇怪的错误

use*_*079 5 c++ opengl qt qml

作为一种爱好,我正在试验 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项目后,不仅shadow失败了。当我移动相机时,错误变得更加奇怪。

向下移动相机后的场景 (-Z) 这是向下移动相机后的帧 (-Z)

使用以下方法在 qml 下渲染场景:

connect(window, &QQuickWindow::beforeRendering, this, &MyApp::renderScene, Qt::DirectConnection);
Run Code Online (Sandbox Code Playgroud)

在渲染场景 I 中:

  • 做一些 OpenGL 传送带设置(为了防止 Qml Scene Graph 的改变,可能是多余的);

    glViewport(0, 0, window->width(), window->height());
    
    glClearColor(0, 0, 0, 1);
    glClearDepth(1);
    glDepthRange(0,1);
    glDepthFunc(GL_LEQUAL);
    
    Run Code Online (Sandbox Code Playgroud)
  • 调用 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-bit, HD 7750

OpenGL:在旧项目中我设置了 3.3,新项目使用 4.3(据我所知)

PS 深度贴图失真是因为我在着色器中使用了一些额外的失真来改善场景中心的阴影。

use*_*079 4

经过一天和许多天都没有答案后,我突然有了灵感!

我怀疑深度缓冲区出了问题,并尝试输出以调试用于渲染和用于渲染全屏四边形的纹理 ID。我尝试关闭渲染到纹理缓冲区交换等等。但我什至不认为真正的问题是在 Qml 这边。

glDepthMask(GL_TRUE); // 42!

这句话就像是42——回答所有问题。看起来 QmlglDepthMask(GL_FALSE);在第一个渲染帧之前调用(但在发出&QQuickWindow::beforeRendering信号之后)。这次调用的结果是,只有首先我的帧才真正通过写入深度缓冲区进行渲染。为什么我认为glDepthMask(GL_FALSE);只调用一次?因为在我插入“42”后,FPS 明显下降,而在我插入glDepthMask(GL_FALSE);用于渲染场景的插槽末尾后,FPS 明显增加。

现在我可以自由旋转“太阳”(阴影)并移动相机,没有任何视觉错误。

耶皮!

新项目的结果