openGL是如何得出F_深度公式的?这是窗口-视口转换吗

openGL是如何得出F_深度公式的?这是窗口-视口转换吗,opengl,transformation,Opengl,Transformation,通过投影矩阵变换点后,我们最终得到范围[-1,1]内的点, 但是,在深度测试一章中,作者提到 F_depth=1/z-1/far/(1/near-1/far)转换视图空间坐标,即z=zeye从[-1,1]转换为[0,1] ,其中一位成员告诉我,公式F_depth实际上是一系列步骤的组合,并概述了这一步骤: #point no.1 正如他所建议的,但这与中给出的F_深度公式完全不同 另一位成员告诉我,[-1,1]到[0,1]是窗口-视口转换,它具有 因此,所有这些对我来说都没有任何意义(对于同样

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

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

#point no.1
正如他所建议的,但这与中给出的
F_深度
公式完全不同

另一位成员告诉我,[-1,1]到[0,1]是窗口-视口转换,它具有

因此,所有这些对我来说都没有任何意义(对于同样适用于openGL的东西,有3个不同的公式和解释),我将重点说明我对这些矛盾想法的疑问:

  • F_深度是从视图空间到窗口的转换的组合吗 空间
  • 深度范围变换和视口变换是否相同 同样的?为什么它们有不同的公式(第1点中的公式)和 另一个
  • F_深度公式是如何得到的?或者构图是如何得到的 将世界空间点转换为[0,1]所做的转换的数量 导致
    F_深度

由于@Rabbit76,最初的部分,详细信息、可能的讨论和信用也是一个巨大的感谢

概述转换过程的步骤包括:

#point no. 2
因此,从步骤3开始: openGL使用a=0,b=1,因此步骤3变为:

    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) .
步骤2的取代基值:

[ zNDC+1 ]/2
替换步骤1中的值,并简化得到:

[ zclip / wclip   +  1 ] /2
现在对于learnopenGL的公式:

[1 + n/zeye]/[1-n/f]  
如果zeye=-zye,我们得到:

F_depth = [1/zeye - 1/n] /[ 1/f - 1/n]  
简化,我们得到相同的结果:

-(zeye + n)/(n-f) * nf/[zeye *n]  
因此,公式直接从眼睛坐标到窗口视口坐标。
此外,深度范围变换是z坐标的窗口-视口变换。

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

在本教程中,声称的深度为

深度=(1/z-1/n)/(1/f-1/n) 其中,
z
是到观察点的距离,
n
是到近平面的距离,
f
是到观察点远平面的距离

问题是为什么上面的公式给出了碎片的深度


对称透视投影矩阵为(请参见):

1/(ta*a)0
0 1/ta 0 0
0 0-(f+n)/(f-n)-2fn/(f-n)
0         0     -1              0
对于深度,我们只对
z
w
组件感兴趣。对于输入顶点(x_眼、y_眼、z_眼、w_眼),剪辑空间z_剪辑和w_剪辑组件的计算公式为:

z_Clip=C*z_眼+D*W_眼
w_剪辑=-z_眼
在哪里

C=-(f+n)/(f-n)
D=-2fn/(f-n)
标准化设备空间z坐标由

z_-ndc=z_-clip/w_-clip
规格化设备空间z坐标映射到深度范围[a,b](请参阅):

depth=a+(a-b)*(z_-ndc+1)/2
当我们假设深度范围为[0,1]且输入顶点为a(x_眼,y_眼,z_眼,1)时,这将导致以下结果:

z_眼*-(f+n)/(f-n)+-2fn/(f-n)
深度=(------------------------------------+1)/2
-z_眼
而且可以转化

-z_眼*(f+n)-2fn
深度=(---------------------------+1)/2
-z_眼*(f-n)
-z_-eye*(f+n)-2fn+-z_-eye*(f-n)
深度=---------------------------------------------
-z_眼*(f-n)*2
-z_眼*(f+n+f-n)-2fn
深度=-------------------------------
-z_眼*(f-n)*2
-z_眼*f-fn-f(n+z_眼)
深度=--------------------------=----------------
-z_眼*(f-n)z_眼(n-f)
由于视图空间z轴指向视口之外,因此从视图点到顶点的
z
距离为
z=-z_-eye
。这导致:

f(n-z)1/z-1/n
深度=-------------=-----------
z(n-f)1/f-1/n

我刚刚发现这个公式的推导过程实际上似乎是直接从眼睛空间到窗口坐标的合成。作者应该解释一下。不,不是。它只是一个approximation@Rabbid76,嗯…我总是怀疑我的理解力,这只能在几周后才能消除。可能是我认为我理解了你能看一下我下面的推导吗?我仍然需要强调一点:“通过投影矩阵变换点后,我们得到的点位于范围
[-1,1]
”。不,我们没有。我们也不在范围
[-w,w]内
。剪辑空间是无限的。查看体积只是该空间中选定的有限子体积,该子体积映射到
[-1,1]
NDC多维数据集(至少在OpenGL中,默认情况下,有不同的约定可供选择)。但是,剪辑空间和NDC之间不仅存在透视分割,还存在剪辑本身。因此,指定一个公式来描述从剪辑或眼睛空间到NDC或窗口空间的转换仅对位于查看体积中的点有效。如果使用透视投影,则会得到错误的结果在“camera”之后,您甚至可以将相机平面中的点除以零-这两种情况在GPU渲染期间都不会发生,因为这些情况在渲染之前通过剪裁消除
-(zeye + n)/(n-f) * nf/[zeye *n]  
[1 + n/zeye]/[1-n/f]