FBO深度纹理附件的最佳设置

3

在使用自定义FBOs时,我一直使用渲染缓冲区进行深度测试。现在,我需要用深度纹理来代替它们(因为我需要在着色器中读取它)。我正在查看不同的来源,如这里,看到GL_FLOAT被用作数据类型。在其他 示例中,使用GL_UNSIGNED_BYTE,有时甚至使用GL_INT。还有内部格式可以是GL_DEPTH_COMPONENT16,GL_DEPTH_COMPONENT24,GL_DEPTH_COMPONENT32。

我的问题是,哪种变化在性能和质量方面最好?我确信,具有32位深度分量的深度测试应该更精确,但数据类型呢?通常应该使用哪一个?


2
传统上,几年前,人们会使用24位深度(带或不带模板),或者在某些廉价卡上使用16位。32位整数深度从未得到良好支持。现在,我只会选择浮点数,它基本上是普遍支持的、快速的,并且没有像整数那样扭曲怪癖 - Damon
1个回答

3
您所描述的使用GL_UNSIGNED_BYTEGL_FLOAT等实际上是像素传输类型。这是OpenGL在从/向缓冲区读取/写入像素数据时使用的类型,在OpenGL中,驱动程序将进行数据类型转换以确保读取/写入的值兼容。在OpenGL ES中,这被完全删除了,但在所有情况下,深度渲染缓冲区的内部格式必须是GL_DEPTH_COMPONENT<X>{F}GL_DEPTH<X>_STENCIL<Y>之一。这些格式定义了内部使用的数据类型和格式。
为获得最佳性能,请将组件类型与像素传输类型匹配,以避免驱动程序像素转换。(例如,GL_FLOAT用于像素传输是GL_DEPTH_COMPONENT32F的良好匹配)。然而,这仅适用于当您想在OpenGL外部使用深度/模板缓冲区的内容(例如使用PBO读取或写入缓冲区)时。
大多数情况下,您可以忽略像素传输格式和类型,只要确保它们是给定内部格式的合法值即可分配深度纹理。您可能不会在OpenGL外部读取它或从客户端内存中提供数据,这是唯一适用的时间。

“忽略”是什么意思?是完全不设置它吗?还是使用任何类型? - Michael IV
@MichaelIV:使用任何类型,因为我相当确定在调用glTexImage2D(...)设置纹理附件时,您正在传递NULL作为像素数据。 NULL表示首先没有像素传输:P但是,如果您要使用PBO将纹理读入客户端内存并使用glReadPixels(...),则像素传输格式/类型非常重要,并且您将遵循我上面解释的规则-匹配组件大小/类型以最小化驱动程序开销。 - Andon M. Coleman
@MichaelIV:我意识到我在回答中忘记讨论精度/性能权衡了。它们已经在问题的评论中提到,24位深度缓冲区是窗口像素格式中最广泛支持的...在FBO中,您有更多的灵活性,但如果您可以使用较小的格式,那么您将获得更好的性能,因为它减少了内存带宽。FP实际上总体上不太精确,但允许更大范围的深度值,特别是在靠近近平面的分数范围内;在某些领域提高精度。 - Andon M. Coleman
1
一个有趣的提示是,在透视投影中,相机附近已经具有更高的精度。因此,当您想要解决更远处的对象时,FP深度缓冲区本身实际上会使情况变得更糟。但是,如果您翻转深度范围,则可以在使用透视投影时使用FP深度缓冲区来更均匀地分配精度(比使用定点深度缓冲区)。有关更多详细信息,请查看此文章 - Andon M. Coleman

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