如何使用深度缓冲区来存储索引

6

我想以稍微不同寻常的方式使用深度缓冲,并且我被所有规范化、缩放和其他操作所搞糊涂了。

我的计划是通过 AMD 的一些人实现空间哈希算法 (pdf 链接)。

tl;dr 版本:通过将 3D 顶点离散化为 (平面 2D) 深度纹理数组,将深度设置为 VertexID,从而加速最近邻搜索。使用深度纹理的原因是进行了一些智能深度测试,甚至可以按排序顺序获得结果,但这在这里不太重要。

我的问题是 VertexID 明显是一个整数,范围从 0 到总顶点数 ParticleCount,但它不能直接使用,因为在 OpenGL 中,顶点着色器的输出必须被规范化为 [-1..1)(或在 DirectX 中为 [0..1))。

因此,我的顶点着色器会执行以下操作:

float depth = 2.0 * gl_VertexID / ParticleCount - 1.0;
gl_Position = vec4(flatCoords, depth, 1.0);

那有点起作用,但是实际存储在当前帧缓冲区绑定的深度纹理中的值让我感到困惑。 如果我无法输出实际整数,并且当以后从深度纹理中读取时,无论我设置什么内部格式(DepthComponent24、32、32f),一切似乎都被规范化为[0..1],我就不太明白浮点深度缓冲区和整数版本之间的区别了。
有人能给我一些建议如何从这些深度纹理中获取顶点ID吗?
谢谢。

在OpenGL中将数值归一化为[-1..1)(或在DirectX中归一化为[0..1)),其中1是包括在内的。 - Nicol Bolas
你说得对,是个小疏忽。但深度测试的默认行为是将深度缓冲区清除为1并使用“小于”比较,因此所有深度为1的点都会被剔除。 - Gigo
1个回答

2
OpenGL中的顶点着色器输出在透视除法后被剪裁到[-1,1],也就是说gl_Position.z/gl_Position.w必须在该范围内。 然而,实际存储在深度缓冲区中的深度值使用当前深度范围(glDepthRange)值重新映射为0..1范围。默认情况下,深度范围是0..1,这相当于
depth_buf_value = 0.5 + 0.5 * gl_Position.z / gl_Position.w;

所以在您的情况下,深度缓冲区最终包含float(gl_VertexID) / ParticleCount的值,因此:

vertex_id = depth_buf_value * ParticleCount

好的,这证实了我尝试做的事情本应该起作用,但它没有。我会尽快回到这个项目中让它正常工作。 - Gigo
1
我有另一个想法:精度如何?深度缓冲区所使用的内部格式让我有些困惑。它被处理为float类型,但存储为规格化的整数?这是否会影响可以表示的范围?ParticleCount可能非常大,达到百万级别,我必须能够可靠地从深度缓冲区中还原粒子索引。 - Gigo
2
将0到1范围内的浮点值转换为给定的内部格式。使用24位整数格式和浮点格式都应该获得相同的精度,因为后者具有24位尾数(23+隐式前导位),可以用于表示整数而不会丢失位。但是,在OpenGL中,由于经过了重新映射的部分,至少会丢失一位精度。但这仍然留下了23位具有> 8百万个不同值的位。 - camenomizoratojoakizunewake

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