这里的文章说:
将 x、y 和 z 除以 w 即可完成此操作。生成的坐标称为标准化设备坐标。现在所有可见的几何数据都位于一个立方体中,其位置在 OpenGL 中的 <-1, -1, -1> 和 <1, 1, 1> 之间,以及 <-1, -1, 0> 和 <1, 1 之间, 1> 在 Direct3D 中。
这对于出于某种特定原因想要测试 Z 坐标的跨平台着色器提出了问题。无论平台如何,有没有办法在同一范围内获得 Z 坐标?
通常避免使用 NDC 空间的非线性 z/w 值。通常通过将绝对顶点 Z 距离传递一个额外的变量来做到这一点。这样东西就可以保持便携。
有趣的问题,但我怀疑它是否可以实现,因为视口转换仍然是固定功能。
首先想到的是使用glDepthRange
(或其可能的 D3D 对应物)将映射从 NDC z 更改为深度。但这不起作用,因为将 [-1,1] 传递给glDepthRange
只会将其钳制为 [0,1] 并且您也不能在 D3D 中将其设置为 [0.5,1],因为在此之前所有内容仍将被剪裁[0,1]。
但我认为您不需要太频繁,因为在片段/像素着色器中,您会获得具有标准化 [0,1] 深度的窗口坐标(我希望 Cg 在此处的行为类似于 GLSL)。在顶点着色器中,您更经常需要世界或视图空间深度,而不是 NDC z。如果您真的需要它,您可以根据着色器中的预处理器定义做出决定。
你在哪里做你想做的 Z 测试?
如果您在片段着色器中执行此操作,那么您不必在意。gl_FragCoord.z
或者任何与此等效的 Cg 在窗口空间中。窗口空间 Z 范围由glDepthRange
; 默认情况下,它从 0 到 1。
如果你在顶点着色器中做这个测试,那么你只需要忍受它。更好的测试可能是在相机空间中完成,而不是剪辑空间或 NDC 空间。至少那时,您通常要处理世界级的距离。