Opengl 延迟着色skybox,在全屏四元后渲染

Opengl 延迟着色skybox,在全屏四元后渲染,opengl,fbo,deferred-rendering,Opengl,Fbo,Deferred Rendering,因此,作为延迟着色器的最后一步,我一直在尝试让skybox正常工作。基本上,我经历了所有常规的延迟着色器步骤,然后使用一些后期处理的东西,如HDR和bloom,最后一步是使用正向着色器渲染成全屏四元体。现在,如果我单独渲染skybox或延迟着色结果,一切看起来都很正常。只有当我最后一次尝试渲染skybox时,它才不会出现在屏幕上 因此,基本上在我使用结果渲染四边形之后,我希望使用几何体过程中的深度值渲染skybox。我尝试过按建议快速设置深度缓冲区,但没有任何效果,我认为问题在于我如何为FBO设

因此,作为延迟着色器的最后一步,我一直在尝试让skybox正常工作。基本上,我经历了所有常规的延迟着色器步骤,然后使用一些后期处理的东西,如HDR和bloom,最后一步是使用正向着色器渲染成全屏四元体。现在,如果我单独渲染skybox或延迟着色结果,一切看起来都很正常。只有当我最后一次尝试渲染skybox时,它才不会出现在屏幕上

因此,基本上在我使用结果渲染四边形之后,我希望使用几何体过程中的深度值渲染skybox。我尝试过按建议快速设置深度缓冲区,但没有任何效果,我认为问题在于我如何为FBO设置深度缓冲区,因为它共享一个模具附件

我对skybox的渲染调用:

//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_附件会把事情搞砸,但我也不明白如果在blit函数中指定深度附件,为什么不能blit它

结果的图像,无天空盒:

编辑


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

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


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

似乎是这样,因为会抛出GL_INVALID_操作,原因之一是“如果掩码包含GL_depth_BUFFER_位或GL_depth_BUFFER_位,并且源和目标深度和模具格式不匹配,则会生成GL_INVALID_操作。”这有点奇怪,因为很多像这样的教程使用它时没有任何问题。我想我必须添加另一种颜色纹理,然后存储深度。我将实施它,看看它如何运行,谢谢您的帮助!为了将来的参考,我使用glfw并尝试设置glfwWindowHint(glfw_深度_位,24);和glfwWindowHint(GLFW_模具_位,8);以及设置GL_DEPTH24_STENCIL8,这对问题没有任何帮助。正如我所说,默认深度缓冲区是实现定义的。这意味着可以猜测您的系统的内部格式,但不能保证这对其他任何人都有效。这不全是阴郁和厄运。实际上,您可以使用R32F纹理中存储的深度来计算世界位置,这将允许您摆脱位置纹理并节省内存/带宽。但这是另一个问题的主题。