openGL 如何得出公式 F_depth 并且这是 window 视口变换

How does openGL come to the formula F_depth and and is this the window viewport transformation

#point no.1

通过投影矩阵变换点后,我们最终得到 [-1,1],
范围内的点 但是,在深度测试章节中,作者提到
F_depth = 1/z-1/far /(1/near - 1/far) 转换 视图 space 坐标 即 z=zeye 从 [-1,1] 转换为 [0,1] .

I've followed this thread,其中一位成员告诉我公式F_depth实际上是一系列完成步骤的组合,并概述了这一步:

    z_Clip = C*z_eye+D*W_eye
    w_Clip = -z_eye
    where C=-(f+n)/(f-n), D=-2fn/(f-n).
    Projective division:
    z_ndc = z_clip/w_clip
    Depth range:
    depth = a + (a-b)*(z_ndc+1)/2
    where glDepthRange(a,b) .

I tried composing the formula as he had suggested, but this is completely different from the F_depth formula given in learnopenGL.

#point no. 2

另外一个成员告诉我[-1,1]到[0,1]是window视口变换,它有一个different formula itself.

所以,所有这些对我来说都没有任何意义(有 3 个不同的公式和解释同样适用于 openGL),我将列出查询我对这些相互矛盾的想法有:

详细信息以及可能的讨论和来源可以是 found here also a huge thanks to @Rabbit76, initial part

概述转换过程的步骤如下:

    1.The projection transformation:
    zclip = Czeye+Dweye
    wclip = -zeye
    where C=-(f+n)/(f-n), D=-2fn/(f-n).
    2.Projective division:
    zNDC = zclip/wclip
    3.Depth range transformation:
    depth = a + (b-a)*(zNDC+1)/2
    where glDepthRange(a,b) .

所以,从第 3 步开始: openGL使用a=0,b=1,所以第3步变成:

[ zNDC+1 ]/2

替换第 2 步的值:

[ zclip / wclip   +  1 ] /2

代入第 1 步的值并简化您得到:

[1 + n/zeye]/[1-n/f]  

现在学习openGL的公式:

F_depth = [1/zeye - 1/n] /[ 1/f - 1/n]  

如果 zeye = -zye,我们得到:

-(zeye + n)/(n-f) * nf/[zeye *n]  

简化我们得到相同的:

[1 + n/zeye]/[1-n/f]  

所以,公式直接从眼睛坐标直接到 window- 视口坐标。 此外,深度范围变换是 z 坐标的 window-视口变换。

@horxCoder 的回答中缺少一些步骤,我想澄清一下。

教程中LearnOpenGL - Depth testing is claimed that the depth at claimed at Perspective projection

depth = (1/z - 1/n) / (1/f - 1/n)

其中z是到视点的距离,n是到近平面的距离,f是到[=31的远平面的距离=].

问题是为什么上面的公式给出一个片段的深度?


对称透视投影矩阵为(见OpenGL Projection Matrix):

1/(ta*a)  0      0              0
0         1/ta   0              0
0         0     -(f+n)/(f-n)   -2fn/(f-n)
0         0     -1              0

对于深度,我们只对 zw 分量感兴趣。对于输入顶点 (x_eye, y_eye, z_eye, w_eye), 剪辑 space z_clipw_clip 分量计算如下:

z_Clip = C * z_eye + D * W_eye
w_Clip = -z_eye

哪里

C = -(f+n) / (f-n)
D = -2fn / (f-n)

标准化设备spacez坐标由Perspective divide

计算
z_ndc = z_clip / w_clip

归一化设备spacez坐标映射到深度范围[a,b](见glDepthRange):

depth = a + (a-b) * (z_ndc+1)/2

当我们假设深度范围是 [0, 1] 并且输入顶点是 Cartesian coordinate (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)

由于视图 space z 轴指向视口外,因此从视点到顶点的 z 距离为 z = -z_eye。这导致:

          f (n - z)        1/z - 1/n
depth  =  -----------  =  -----------
          z (n - f)        1/f - 1/n