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

标签 c++ qt opengl qml

作为一种爱好,我正在试验 OpenGL 并使用 Qt+OpenGL 编写我自己的愚蠢引擎。最后的成功是构建实体系统框架,它可以使用附加的物理引擎 (BulletPhysics) 渲染带有阴影的场景(通过渲染到纹理到 RenderBuffer)。

之后我更新到Qt 5.2,完全用Qml表达了(之前没试过)。我对 2d qml 图形进行了一些实验,并决定将 qml 用于用户界面,但拒绝 2d 项目并返回到 3d。我创建了新的 qml 项目,尝试在 qml 下渲染一些东西,如 Scene Graph - OpenGL Under QML例子。之后,我将我的旧代码从 3d 项目移到新项目,并进行了一些小的重构(应该不会影响任何东西)。

在这一刻,我厌倦了一些奇怪的错误。似乎第一帧是根据需要渲染的,但之后就出现了问题。

Scene view 这是一个或多或少正常的帧(在任何移动之前)

在左上角我是输出深度缓冲区(阴影贴图)。在右上角,我用 qml 制作了一些自定义滚动条。我正在使用这个滚动条来改变阴影贴图旋转和移动相机。当滚动条居中时,没有任何移动。当我改变一些东西时,场景变得丑陋,我不知道为什么。

Scene view after some shadow map rotate 这是一些阴影贴图旋转后的帧

我看到阴影贴图深度缓冲区没有改变(为什么?o_0)并且场景中的阴影出错了。但是,在将我的旧代码重构为 qml 项目后,不仅影子失败了。当我移动相机时,错误变得更加奇怪。

Scene after moving camera down (-Z) 这是将相机向下移动 (-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 什么都不显示。

Scene with camera moved 通过 XY 轴再次移动相机一次。人的角轮廓仍然可见,并产生奇怪的效果

一些截图:

Old project 旧项目(没有 qml)

Old project - big screenshot 旧项目(大截图)

Broken resize 在新项目中,窗口大小调整也被破坏

它可以是什么?

环境: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); 用于渲染我的场景的插槽末尾后增加。

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

嗨!

Result in new project

关于c++ - 在 Qml 场景下使用 OpenGL 渲染时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21870004/

相关文章:

c++ - 如何将当前日期以数字形式放入 QLabel 中?

qt - PyQt5翻译: is it possible to run pylupdate5 from Python?

c# - 将 OpenGL 场景绘制到 C# 位图;屏幕外被剪辑

c++ - 在 OpenGL 中使用多个纹理

opengl - 顶点着色器的哪些输出变量将被插值?

python - 与boost python的静态链接

c++ - 终止阻塞的 pthreads 线程

c++ - 发布 Qt C++ GUI 程序的最简单方法?

c++ - 在 C++ 中混合 RTTI 标志

c++ - 模板类型的模板特化