DirectX 负 W

DirectX negative W

我真的很想为这个非常基本(乍一看)的问题找到答案。

为简单起见,在进一步讨论期间禁用了深度测试(这没什么大不了的)。

例如,我们有下一个 float4 坐标的三角形(变换后)。

顶部中心点:(0.0f, +0.6f, 0.6f, 1f)

基本点1:(+0.4f, -0.4f, 0.4f, 1f),

基本点2:(-0.4f, -0.4f, 0.4f, 1f),

我正在发送 float4 作为输入并直接使用 VertexShader(没有变换),所以我确定输入。我们的结果是合理的:

但是如果我们开始将 CenterPoint 移动到相机位置点,我们会得到什么。在我们的例子中,我们没有相机,所以将把这个点移到负无穷大。 只要 w(带 z)为正,我就会得到相当合理的结果。 例如,(0.0f, +0.006f, 0.006f, .01f) – 看起来一样。

但是如果我使用下一个坐标(0.0f、-0.6f、-1f、-1f)呢? (注意:我们必须切换点或更改光栅器以防止剔除)。

根据大量资源,我将进行如下测试:-w < z < w,因此 GPU 应该削减该点。是的,原则上,我看不出有什么意义。但是三角形仍然可见!好的,根据大量其他资源(和我个人的理解),我们将有像 (x/w, y/w, z/w) 这样的划分所以结果应该是 (0, 0.6, 1)。但是我得到

即使这个结果有一定的意义(一个点远远落后于 as),DirectX(我认为它更像是 GPU)在这种情况下是如何工作的(在无限点的情况下)和负 W)?

看来很基础的东西我都不知道,但好像没人知道。

[已添加]:我想指出点 w < 0 - 不是真正的输入。 在现实生活中,这些点是矩阵转换的结果,根据数学(标准 Direct sdk 和其他地方使用的数学)对应于出现在相机位置后面的点。 是的,那个点被剪掉了,但问题是关于包含这个点的奇怪三角形。

[简答]:裁剪本质上不仅仅是z/w检查和除法(详见下文)。

理论上,NDC深度分为两个不同的区域。下图显示了 znear = 1, zfar = 3 的这些区域。水平轴显示视图-space z,垂直轴显示标准投影变换的结果 NDC 深度:

我们可以看到 view-space z of 1 and 3 (znear, zmax) 之间的部分被映射到 NDC 深度 0 到 1。这是我们真正感兴趣的部分. 然而,view-space z 为负的部分也会产生正的 NDC 深度。但是,这些是折叠产生的部分。也就是说,如果你从三角形的一个角开始慢慢减小 z(连同 w),从 znear 和 zfar 之间的区域开始,你会观察到以下情况:

  • 我们从 znear 和 zfar 开始,一切都很好
  • 一旦我们通过 znear,该点就会被剪掉,因为 NDC 深度 < 0。
  • 当我们在视图-space z = 0 时,该点也有 w = 0 且没有有效投影。
  • 随着我们进一步减小视图-space z,该点再次获得有效投影(从无穷远开始)并以正 NDC 深度返回。

然而,这最后一部分是相机后面的区域。于是,进行了齐次剪裁,这样这部分也被znear剪裁剪掉了。

检查旧的D3D9 documentation for the formulas and some more illustrative explanations here