2

这意味着此时投影已经完成。这篇文章给了我们OpenGL使用的投影矩阵,影响一个点z坐标的因素是行:

[ 0 0 -(f+n)/(f-n) -2fn/(f-n) ]

请注意,计算此矩阵是为了将“金字塔”平截头体制成一个单位立方体。这意味着在应用此矩阵后,z 坐标也已映射到 [0,1]。

然后,深度值精度一章的作者告诉我们:这些视图空间中的 z 值可以是截锥体近平面和远平面之间的任何值,我们需要一些方法将它们转换为 [0,1]。问题是为什么在这一点上,当我们在应用投影矩阵时已经映射了它。

此外,他说:像这样的线性深度缓冲区: F_depth=z-near/(far-near)从未使用过,为了正确的投影属性,使用非线性深度方程:

F_depth= (1/z- 1/near)/(1/far - 1/near)

但是,正如我们所见,z 在范围内使用:

[ 0 0 -(f+n)/(f-n) -2fn/(f-n) ]

这似乎是线性的。

所有这些自相矛盾的陈述让我非常困惑何时计算和比较片段的深度,以及实际用于计算它的方程是什么。在我的理解中,在应用 OpenGL 投影矩阵之后应该不再计算深度,但是在阅读完这篇文章后我真的很困惑。任何澄清?

4

1 回答 1

1

透视投影中,由于透视分割,深度不是线性的。

当一个顶点坐标被投影矩阵变换时,裁剪空间坐标被计算出来。裁剪空间坐标是一个齐次坐标。现在所有不在裁剪空间(在Viewing frustum中)的几何图形都被裁剪了。裁剪规则是:

-w <=  x, y, z  <= w

x之后,通过将、yz分量除以w分量(透视除法)来计算归一化的设备空间坐标。NDC 是笛卡尔坐标,标准化设备空间是一个唯一的立方体,左、下、近为 (-1, -1, -1),右、上、远为 (1, 1, 1)。立方体中的所有几何图形都投影在二维视口上。

请注意,齐次顶点坐标乘以透视投影矩阵(剪辑空间)后,z 分量是“线性的”,但不在范围 [-1, 1] 内。裁剪和透视分割后,z 坐标在 [-1, 1] (NDC) 范围内,但不再是“线性”。

深度缓冲区可以存储范围 [0, 1] 中的值。因此,z标准化设备空间的分量必须从 [-1.0, 1.0] 映射到 [0.0, 1.0]。


在透视投影中,投影矩阵描述了从针孔相机看到的世界中的 3D 点到视口的 2D 点的映射。
相机平截头体(截断的金字塔)中的眼睛空间坐标映射到立方体(标准化设备坐标)。

透视投影矩阵可以由平截头体定义。
距离leftright和是近平面bottomtop从视图中心到截锥体侧面的距离。nearfar指定到平截头体的近平面和远平面的距离。

r = right, l = left, b = bottom, t = top, n = near, f = far

x:    2*n/(r-l)      0              0                0
y:    0              2*n/(t-b)      0                0
z:    (r+l)/(r-l)    (t+b)/(t-b)    -(f+n)/(f-n)    -1
t:    0              0              -2*f*n/(f-n)     0

如果投影是对称的,并且视线是平截头体的对称轴,则矩阵可以简化为:

a  = w / h
ta = tan( fov_y / 2 );

2 * n / (r-l) = 1 / (ta * a)
2 * n / (t-b) = 1 / ta
(r+l)/(r-l)   = 0
(t+b)/(t-b)   = 0

对称透视投影矩阵为:

x:    1/(ta*a)  0      0              0
y:    0         1/ta   0              0
z:    0         0     -(f+n)/(f-n)   -1
t:    0         0     -2*f*n/(f-n)    0

也可以看看

眼睛空间坐标到底是什么?

如何在片段着色器中使用 gl_FragCoord.z 在现代 OpenGL 中线性渲染深度?

于 2020-07-25T05:13:11.640 回答