在 @horxCoder 的答案中缺少一些步骤,我想澄清一下。
在教程中LearnOpenGL - 深度测试据称深度为透视投影 is
depth = (1/z - 1/n) / (1/f - 1/n)
where z
是到视点的距离,n
是到近平面的距离,f
是到远平面的距离视锥体.
问题是为什么片段的深度是由上面的公式给出的?
对称透视投影矩阵是(参见OpenGL 投影矩阵):
1/(ta*a) 0 0 0
0 1/ta 0 0
0 0 -(f+n)/(f-n) -2fn/(f-n)
0 0 -1 0
对于深度,我们只感兴趣z
and w
成分。对于输入顶点(x_眼、y_眼、z_眼、w_眼),剪辑空间z_clip and w_clip分量的计算方法为:
z_Clip = C * z_eye + D * W_eye
w_Clip = -z_eye
where
C = -(f+n) / (f-n)
D = -2fn / (f-n)
标准化设备空间z坐标由以下公式计算观点分歧
z_ndc = z_clip / w_clip
标准化设备空间z坐标映射到深度范围[a, b] (see glDepthRange):
depth = a + (a-b) * (z_ndc+1)/2
当我们假设深度范围是[0, 1]输入顶点是笛卡尔坐标 (x_eye, y_eye, z_eye, 1),这导致以下结果:
z_eye * -(f+n) / (f-n) + -2fn / (f-n)
depth = (------------------------------------------ + 1) / 2
-z_eye
并且可以变形
-z_eye * (f+n) - 2fn
depth = (-------------------------- + 1) / 2
-z_eye * (f-n)
-z_eye * (f+n) - 2fn + -z_eye * (f-n)
depth = ---------------------------------------------
-z_eye * (f-n) * 2
-z_eye * (f+n+f-n) - 2fn
depth = -------------------------------
-z_eye * (f-n) * 2
-z_eye * f - fn -f (n + z_eye)
depth = ----------------------- = ----------------
-z_eye * (f-n) z_eye (n - f)
由于视图空间 z 轴指向视口之外,因此z
从视点到顶点的距离是z = -z_eye
。这导致:
f (n - z) 1/z - 1/n
depth = ----------- = -----------
z (n - f) 1/f - 1/n