【问题标题】:Deferred shading skybox, rendered after full screen quad延迟着色天空盒,在全屏四边形之后渲染
【发布时间】:2015-10-19 17:02:01
【问题描述】:

因此,作为延迟着色器的最后一步,我一直在尝试让天空盒工作。基本上我会完成所有常规的延迟着色器步骤,然后使用一些后期处理东西,如 HDR 和绽放,最后一步使用前向着色器渲染到全屏四边形。现在,如果我只是单独渲染天空盒或延迟着色结果,一切看起来都很好。当我尝试最后渲染天空盒时,它并没有出现在屏幕上。

所以基本上在我用结果渲染四边形之后,我想使用几何通道中的深度值来渲染天空盒。我已经尝试按照Deferred Rendering Skybox OpenGL 的建议对深度缓冲区进行 blitting,但它没有任何效果,我认为问题在于我如何为 FBO 设置深度缓冲区,因为它共享一个模板附件。

我对天空盒的渲染调用:

//draw skybox
glEnable(GL_DEPTH_TEST);

glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, mWindowWidth, mWindowHeight, 0, 0, mWindowWidth, mWindowHeight, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Draw skybox as last
glDepthFunc(GL_LEQUAL);  // Change depth function so depth test passes when values are equal to depth buffer's content
ShaderMan.bindShader(SKY_BOX_SHADER);
glm::mat4 view = glm::mat4(glm::mat3(CameraMan.getActiveCamera()->getViewMatrix()));    // Remove any translation component of the view matrix
glm::mat4 projection = CameraMan.getActiveCamera()->getProjectionMatrix();
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("viewMatrix"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("projectionMatrix"), 1, GL_FALSE, glm::value_ptr(projection));
// skybox cube
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("skybox"), 0);
mSkybox.render();
glDepthFunc(GL_LESS); // Set depth function back to default
ShaderMan.unbindShader();

以及我如何设置延迟 FBO

//POSIITON
glGenTextures(1, &mPositionTexture);
glBindTexture(GL_TEXTURE_2D, mPositionTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
//Nearest min mag filters since we dont want interpolated values
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glFrameBuffer attaches a texture as a color attachment, depth attachment or stencil etc
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mPositionTexture, 0);

glGenTextures(1, &mNormalTexture);
glBindTexture(GL_TEXTURE_2D, mNormalTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mNormalTexture, 0);

//Combined color and specular buffer
glGenTextures(1, &mSpecularAlbedoTexture);
glBindTexture(GL_TEXTURE_2D, mSpecularAlbedoTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, mWindowWidth, mWindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, mSpecularAlbedoTexture, 0);

//Depth & stencil texture for the FBO
glGenTextures(1, &mDepthTexture);
glBindTexture(GL_TEXTURE_2D, mDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, mWindowWidth, mWindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, mDepthTexture, 0);

// final
glGenTextures(1, &mFinalTexture);
glBindTexture(GL_TEXTURE_2D, mFinalTexture);
///Used to be GL_RGBA only
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, mWindowWidth, mWindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, mFinalTexture, 0);

我在想 GL_DEPTH_STENCIL_ATTACHMENT 是什么搞砸了,但我也看不出为什么你不应该能够在 blit 函数中指定深度附件时对它进行 blit

结果的图像,没有天空盒:result

编辑

我尝试搜索了一下并将格式更改为 GL_DEPTH_24_STENCIL8 以防主 fbo 具有不同的浮点格式,但这也没有帮助。

【问题讨论】:

    标签: opengl fbo deferred-rendering


    【解决方案1】:

    您不应尝试将 FBO 深度缓冲区blit 到默认深度缓冲区。要从一个深度缓冲区到另一个深度缓冲区,两者的内部格式必须完全相同。虽然您可以定义 FBO 的格式,但默认深度缓冲区是实现定义的。您也许可以通过反复试验来推断其格式,但该解决方案将无法移植。

    一种解决方案是在几何传递期间将深度写入 R32F 纹理颜色附件。稍后,当您将天空盒绘制到默认帧缓冲区时,您可以将 R32F 纹理绑定到采样器并在片段着色器中读取该像素的深度。仅将天空盒输出到深度为 0.0f 的片段。

    【讨论】:

    • 似乎是这种情况,因为 GL_INVALID_OPERATION 被抛出,原因之一是“如果掩码包含 GL_DEPTH_BUFFER_BIT 或 GL_DEPTH_BUFFER_BIT 并且源和目标深度和模板格式不匹配,则会生成 GL_INVALID_OPERATION。”这有点奇怪,因为像learnopengl.com/#!Advanced-Lighting/Deferred-Shading 这样的很多教程都使用它没有问题。我想我必须添加另一种颜色纹理并存储深度。我会实现它,看看它是如何进行的,谢谢你的帮助!
    • 为了将来的参考,我正在使用 glfw 并尝试设置 glfwWindowHint(GLFW_DEPTH_BITS, 24);和 glfwWindowHint(GLFW_STENCIL_BITS, 8);以及设置 GL_DEPTH24_STENCIL8 这对解决问题没有任何帮助。
    • 正如我所说,默认深度缓冲区是实现定义的。这意味着可以猜测 your system 上的内部格式,但不能保证这对其他人有效。这并不全是悲观和厄运。您实际上可以使用存储在 R32F 纹理中的深度来计算世界位置,这将允许您摆脱位置纹理并节省内存/带宽。不过,这是一个不同问题的主题。
    猜你喜欢
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多