1
#point no.1

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

我已经关注了这个帖子,其中一位成员告诉我,该公式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) .

我尝试按照他的建议编写公式,但这与learnopenGLF_depth中给出的公式完全不同。

#point no. 2

另一个成员告诉我 [-1,1] 到 [0,1] 是窗口视口转换,它本身具有不同的公式

所以,所有这些对我来说都没有任何意义(对于同样的事情,对于 openGL 有 3 个不同的公式和解释),我将针对这些相互矛盾的想法提出疑问:

  • F_depth 是从视图空间到窗口空间的转换的组合吗?
  • 深度范围变换和视口变换是一样的吗?为什么他们有不同的论坛(此链接Point no.1中的一个和另一个
  • F_depth公式是怎么得到的?或者,将世界空间点转换为 [0,1] 的变换组合是如何产生的F_depth
4

2 回答 2

1

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

在教程LearnOpenGL - 深度测试中声称在透视投影中声称的深度是

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

其中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

对于深度,我们只对zandw组件感兴趣。对于输入顶点(x_eye, y_eye, z_eye, w_eye),裁剪空间z_clipw_clip分量通过以下方式计算:

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

在哪里

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

归一化的设备空间z坐标由透视除法计算

z_ndc = z_clip / w_clip

归一化的设备空间z坐标映射到深度范围[a, b](参见 参考资料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
于 2020-07-26T15:04:55.090 回答
1

详细信息和可能的讨论和信用可以在这里找到也非常感谢@Rabbit76,问题的最初部分在这里

概述转换如何进行的步骤是:

    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]  

现在学习learnopenGL的公式:

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]  

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

于 2020-07-26T09:11:02.813 回答