10

我有帧缓冲区,具有深度组件和 4 个颜色附件和 4 个纹理

我在其中绘制了一些东西并在之后解除绑定缓冲区,使用 4 个纹理进行片段着色器(延迟照明)。后来我想在屏幕上画更多的东西,使用我的帧缓冲区中的深度缓冲区,这可能吗?

我尝试再次绑定帧缓冲区并指定 glDrawBuffer(GL_FRONT),但它不起作用。

4

3 回答 3

13

就像 Nicol 已经说过的,您不能直接使用 FBO 深度缓冲区作为默认帧缓冲区的深度缓冲区。

但是您可以使用EXT_framebuffer_blit扩展(从 GL 3 开始应该是核心)将 FBO 的深度缓冲区复制到默认帧缓冲区:

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, 
                  GL_DEPTH_BUFFER_BIT, GL_NEAREST);

如果不支持此扩展(当您已经拥有 FBO 时我怀疑),您可以使用深度纹理作为 FBO 的深度附件,并使用带纹理的四边形和写入gl_FragDepth. 虽然这可能比直接覆盖它要慢。

于 2012-03-28T19:53:34.210 回答
10

我刚刚体验到,在使用 glBlitFramebuffer 时,将深度缓冲区从渲染缓冲区复制到主(上下文提供的)深度缓冲区是非常不可靠的。仅仅因为您不能保证格式确实匹配。使用 GL_DEPTH_COMPONENT24 作为我的内部深度纹理格式在我的 AMD Radeon 6950(最新驱动程序)上不起作用,因为 Windows(或驱动程序)决定使用相当于 GL_DEPTH24_STENCIL8 作为我的前/后缓冲区的深度格式,虽然我没有要求任何模板精度(像素格式描述符中的模板位设置为 0)。当使用 GL_DEPTH24_STENCIL8 作为我的帧缓冲区的深度纹理时,Blitting 按预期工作,但我在这种格式上遇到了其他问题。第一次尝试在 NVIDIA 卡上运行良好,所以我很确定我没有搞砸。

最有效的方法(根据我的经验)是通过着色器进行复制:

片段程序(又名像素着色器)[GLSL]

#version 150

uniform sampler2D depthTexture;
in vec2 texCoords; //texture coordinates from vertex-shader

void main( void )
{
    gl_FragDepth = texture(depthTexture, texCoords).r;
}

用于复制的 C++ 代码如下所示:

glDepthMask(GL_TRUE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glEnable(GL_DEPTH_TEST); //has to be enabled for some reason
glBindFramebuffer(GL_FRAMEBUFFER, 0);
depthCopyShader->Enable();
DrawFullscreenQuad(depthTextureIndex);

我知道线程很旧,但这是我在谷歌上搜索我的问题时的第一个结果,所以我想尽可能保持一致。

于 2013-06-23T20:11:21.280 回答
2

您不能将图像(颜色或深度)附加到默认帧缓冲区。同样,您不能从默认帧缓冲区中获取图像并将它们附加到 FBO。

于 2012-03-28T19:18:30.293 回答