2011-06-14 99 views
9

我想获取纹理当前深度缓冲区,以便在着色器中访问它。由于各种原因,我不能做一个单独的深度传球,但需要复制已经渲染的深度。如何将深度缓冲区复制到GPU上的纹理?

glReadPixels会涉及CPU并可能导致性能下降,据我所知glBlitFramebuffer不能深入到颜色,只能深入到深度。

如何在GPU上做到这一点?

+0

我有同样的问题,你做到了吗? – 2012-07-05 16:09:33

回答

7

这样做的现代方法是使用FBO。为其添加颜色和深度纹理,渲染,然后禁用FBO,并使用纹理作为渲染到默认帧缓冲区的着色器的输入。

所有关于FBO需要的细节都可以在here找到。

+0

我写了一个C++类,它设置了一个只有深度的FBO:https://github.com/mfichman/simple-fast-renderer/blob/master/src/DepthRenderTarget.cpp。如果启用仅限深度的FBO,则可以像平常一样进行渲染 - 但是当完成后,您会在纹理中获得深度信息。我用它来做阴影贴图,但它也适用于你。 – 2014-04-10 19:05:06

5

将深度缓冲区复制到纹理非常简单。如果您创建了一个未打开glTexImage *的新纹理,则可以使用glCopyTexImage2D。这会将帧缓冲区中的像素复制到纹理。要复制深度像素,请使用GL_DEPTH_COMPONENT格式。我建议GL_DEPTH_COMPONENT24。

如果您以前创建了具有深度组件格式的纹理(即:在第一帧之后的任何时候),则可以使用glCopyTexSubImage2D直接复制到此图像数据中。

它似乎也好像在着色器中访问深度组件纹理时遇到问题,因为您想复制深度到颜色(这是不允许的)。如果你是,那么这是一个问题,你应该得到解决。

无论如何,复制应该是最后的手段。您应该尽可能使用framebuffer对象。直接渲染你的纹理。

3

最好的方法是使用FBO,以获得更好的性能和一些编码风格问题。 如果您不感兴趣,请查看此代码。这是从我年轻的时候开始的(并且不知道FBO存在)

int shadowMapWidth = 512; 
int shadowMapHeight = 512; 
glGenTextures(1, &m_depthTexture); 

glBindTexture(GL_TEXTURE_2D, m_depthTexture); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); 
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 512,512); 
+0

如果您使用GL_DEPTH_COMPONENT24,效果会更好! – 2011-06-16 12:27:35

+0

这是为什么?你能解释一下吗? – 2015-02-03 07:46:50