iPhone Dev:渲染深度缓冲到纹理会产生黑色纹理

时间:2011-09-12 12:48:50

标签: iphone opengl-es textures shadow depth

编辑:我把FBO排除在外,以确保问题不是来自那里,所以现在我只是做以下事情:

设置纹理:

GLuint FB0Texture;
glGenTextures(1, &FB0Texture);
glBindTexture(GL_TEXTURE_2D, FB0Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size.width, size.height, 
                 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);

然后渲染:

[self drawScene];

[(EAGLView *)self.view bindFB0];

glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 320, 480);

[self drawFullScreenQuad]; (it's actually not full screen so I can see both the 3d scene and the resulting texture)

我得到了相同的结果!如果我将FB0Texture设置为“DEPTH_COMPONENT”纹理,则为黑色纹理,但如果我将FB0Texture设置为常规GL_RGBA纹理,则为普通场景...

所以我猜我要么设置深度纹理错误,要么我在渲染中做错了会导致RGBA纹理看起来正常但深度纹理被搞砸了? GL_DEPTH_TEST已启用且工作正常(模型看起来正确)所以我认为实际渲染没有任何问题,但此时我急需线索......

请帮忙!

// END OF EDIT

我正在尝试在iphone上实现一些基本的阴影贴图,但我坚持将深度值渲染到纹理......这让我发疯,我显然做错了但却无法弄清楚它是什么。 ..

所以我在做什么:

  • 设置默认帧缓冲,附加颜色渲染缓冲区和深度渲染缓冲区
  • 设置一个新的帧缓冲区(称之为FB0),将纹理附加到深度组件

然后当我渲染时:

  • 将场景绘制到FB0
  • 切换到默认帧缓冲区
  • 使用FB0作为纹理绘制全屏四边形

我得到......什么都没有! (我得到一个完整的白色纹理)

如果我将纹理附加到FB0的颜色分量而不是深度组件,一切正常,就像我将场景绘制到FB0,然后使用FB0作为纹理来绘制全屏四边形,我看到的确切如果我直接绘制到默认的帧缓冲区,我会看到什么。

然而,当我将纹理附加到深度组件时,我得到的就是这个白色的屏幕/纹理。

一些代码:

设置缓冲区:

// Create default framebuffer object.
glGenFramebuffers(1, &defaultFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);

// Create color render buffer and allocate backing store.
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

// Create depth render buffer
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 320, 480); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);


// Create Depth Map Frame Buffer

glGenFramebuffers(1, &FB0);
glBindFramebuffer(GL_FRAMEBUFFER, FB0);

// Attach texture to depth component        

glGenTextures(1, &FB0Texture);
glBindTexture(GL_TEXTURE_2D, FB0Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width, size.height, 
                 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0);

glFramebufferTexture2D(GL_FRAMEBUFFER, 
                       GL_DEPTH_ATTACHMENT, 
                       GL_TEXTURE_2D, 
                       FB0Texture, 
                       0);

如果我在此之后检查帧缓冲区的状态,我没有收到任何错误消息,所以我假设缓冲区是正确创建的。

然后在渲染中:

[(EAGLView *)self.view setFB0]; (just binds the framebuffer)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

[self drawScene];

[(EAGLView *)self.view setFramebuffer]; (binds back the default frame buffer)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

[(EAGLView *)self.view bindFB0Texture];

[self drawFullScreenQuad];

[(EAGLView *)self.view presentFramebuffer];

此时我希望看到黑色和白色纹理,灰度等级表示深度,但我只是得到一个纯白色四边形/纹理。

同样,如果我将FB0Texture附加到GL_COLOR_ATTACHMENT0而不是GL_DEPTH_ATTACHMENT,一切都按预期工作,我的场景会正确渲染到纹理。所以我猜问题来自于我如何附加纹理,或者可能是我正在做的事情的顺序?

1 个答案:

答案 0 :(得分:1)

您的问题可能在于,您只是将深度纹理附加到渲染到纹理FBO,而不是附加颜色缓冲区。

如果这不起作用,Apple在他们的技术文档中建议您应该使用GL_OES_depth_texture扩展名,但我无法在渲染纹理深度方面自行完成这项工作虽然使用它似乎可以显着提高我对颜色渲染到纹理图像的深度测试的保真度。

编辑:哎呀,这就是你已经在做的事情。我应该更彻底地阅读这个问题,抱歉!

我目前也遇到这个问题,所以如果它已经解决了,我很想知道怎么做!

编辑#2:我已经在自己的情况下解决了这个问题。深度缓冲区将深度存储在非线性空间中,因此有必要将深度转换回线性空间以使其正确可视化(这可以通过投影近距离和远距离平面信息来实现)。我遇到的问题是我的大部分深度信息都存储在0.995到1.0的范围内,这意味着我的眼睛看起来像是一个完全白色的纹理。这可能是你在获得全白纹理时遇到的问题。

作为旁注,Xcode 4.2的真棒OpenGL ES快照功能帮助我解决了这个问题。它允许您在上下文中可视化所有纹理和渲染缓冲区对象,如果数据是非线性的,甚至可以为您重新调整颜色。正如你可能猜到的那样,这就是我弄清楚它的方法。