OpenGL,如何使用framebuffer中的depthbuffer作为通常的深度缓冲区

ShP*_*vel 9 opengl framebuffer depth-buffer

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

我在其中绘制了一些东西,然后取消绑定缓冲区,使用4个纹理进行片段着色器(延迟光照).后来我想在屏幕上绘制更多东西,使用我的帧缓冲区中的深度缓冲区,是否可能?

我尝试再次绑定framebuffer并指定glDrawBuffer(GL_FRONT),但它不起作用.

Chr*_*ica 10

就像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);
Run Code Online (Sandbox Code Playgroud)

如果不支持此扩展(我怀疑你已经有FBO),你可以使用FBO深度附件的深度纹理,并使用纹理四边形和写入的简单传递片段着色器将其渲染到默认帧缓冲区gl_FragDepth.虽然这可能比仅仅轻轻一点慢.


Mar*_*ius 9

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

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

片段程序(又名Pixel-Shader)[GLSL]

#version 150

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

void main( void )
{
    gl_FragDepth = texture(depthTexture, texCoords).r;
}
Run Code Online (Sandbox Code Playgroud)

用于复制的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);
Run Code Online (Sandbox Code Playgroud)

我知道线程已经过时了,但这是我的第一个结果之一,因此我想尽可能保持一致.