使用帧缓冲将深度缓冲区渲染到纹理中。

3

我正在使用JOGL,但这个问题适用于OpenGL。似乎有类似的问题存在,但它们要么针对GLSL代码,要么涉及复制帧缓冲区的内容,要么是一般性建议-使用帧缓冲对象代替glCopyTexSubImage2D

问题

我正在进行一些阴影映射。如何使用帧缓冲对象将深度通道直接渲染到纹理中?

您能否发布一段初始化纹理和帧缓冲对象的代码块,以及在渲染场景之前初始化所有内容的代码?

目前,我使用glCopyTexSubImage2D。我像这样初始化纹理:

glGenTextures(1, &textureNo)
glBindTexture(GL_TEXTURE_2D, textureNo)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL)
glTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, null)

然后我像这样呈现:
glBindTexture(GL_TEXTURE_2D, textureNo)
glClear(GL_DEPTH_BUFFER_BIT)
drawScene()
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 2048, 2048)

这很好用,纹理最终保存了场景的深度通道 - 这意味着我的投影矩阵和视图矩阵已正确设置,可以从光源的角度查看场景。但我想使用帧缓冲对象。

如何修改上述内容以直接渲染到纹理而不是使用帧缓冲对象?

编辑:

这是我尝试过的。我首先初始化了帧缓冲对象:

glGenFramebuffers(1, &fbo)

我接下来这样渲染:
glBindFramebuffer(GL_FRAMEBUFFER, fbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textureNo, 0)
glBindTexture(GL_TEXTURE_2D, textureNo)
drawScene()

我确认上述内容适用于类型为GL_RGBGL_COLOR_ATTACHMENT0的纹理,但似乎不适用于类型为GL_DEPTH_COMPONENTGL_DEPTH_ATTACHMENT的纹理——深度通道未被渲染到上面的textureNo纹理中。


你是否尝试过一些不起作用的东西,或者只是在寻找有人为您编写代码,以便您可以将其复制粘贴到应用程序中?FBOs并不是很难理解。 - Nicol Bolas
实际上,我写了一些不起作用的东西。我正在初始化一个帧缓冲对象,然后将纹理附加到它上面。但是,这没有将场景的深度通道渲染到纹理中。有趣的是,当我使用帧缓冲对象将场景渲染到常规的 GL_RGB 纹理时,它可以正常工作。我在文档中没有找到任何关于如何使用帧缓冲对象来渲染深度通道与渲染 RGB 通道有何不同的内容。 - axel22
我正在使用Scala的JOGL薄封装(https://github.com/axel22/scalagl)编写代码,它旨在提供一些面向对象风格的资源管理和更结构化的编码。因此,我不得不稍微调整我的代码-我已经编辑了问题以展示我所做的事情。 - axel22
1个回答

4
假设这是所有的FBO设置代码,我没有看到您调用{{link1:glCheckFramebufferStatus}}的部分。您知道,这个函数会告诉您您的{{link2:FrameBuffer对象不完整}},因此渲染会失败。

具体来说,它会给您提供GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER​,因为您没有设置有效的绘制缓冲区。如果您不使用颜色附件,则需要使用{{link3:glDrawBuffer}}将所有颜色缓冲区写入设置为GL_NONE

这是常见的FBO陷阱; 您不会是第一个没有看到它的人。但这就是为什么在修改FBO后始终检查glCheckFramebufferStatus至关重要。


@axel22: "不确定为什么",出于同样的原因,您必须将绘制缓冲区设置为无。 - Nicol Bolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接