我一直试图想出这种关系,但我不能,也许我只是不寻找正确的事情。如果我使用Vector3.Project将世界空间坐标投影到剪辑空间,X和Y坐标是有意义的,但我无法弄清楚它是如何计算Z(0..1)坐标的。例如,如果我的近平面是1并且farplane是1000,我将Vector3(0,0,500)(摄像机中心,远距离平面的50%)投影到我得到的屏幕空间(1050,500,.9994785)
得到的X和Y坐标非常有意义,但我不明白它在哪里得到Z值。
我需要这个,因为我实际上是在尝试UNPROJECT屏幕空间坐标,我需要能够选择一个Z值告诉它我想要世界空间坐标的相机距离,但是我不理解剪辑空间Z(0-1)和世界空间Z(近平面 - 飞机)之间的关系。
如果这有帮助,我的转换矩阵是:
World = Matrix.Identity;
//basically centered at 0,0,0 looking into the screen
View = Matrix.LookAtLH(
new Vector3(0,0,0), //camera position
new Vector3(0,0,1), //look target
new Vector3(0,1,0)); //up vector
Projection = Matrix.PerspectiveFovLH(
(float)(Math.PI / 4), //FieldOfViewY
1.6f, // AspectRatio
1, //NearPlane
1000); //FarPlane
答案 0 :(得分:1)
标准透视投影在场景深度和深度缓冲值之间创建倒数关系,而不是线性关系。这导致更高百分比的缓冲精度被应用于更接近近平面的对象,而不是更接近远平面的对象,这通常是期望的。至于实际的数学,这是细分:
投影矩阵的右下2x2元素(对应于z和w)是:
[far / (far - near) ] [1]
[-far * near / (far - near)] [0]
这意味着在乘以z' = z * far / (far - near) - far * near / (far - near)
和w' = z
之后。在此步骤之后,存在透视分割z'' = z' / w'
。
在你的具体情况下,数学计算得出你得到的值:
z = 500
z' = z * 1000 / (1000 - 999) - 1000 / (1000 - 999) = 499.499499499...
w' = z = 500
z'' = z' / w' = 0.998998998...
要恢复原始深度,只需撤消操作:
z = (far / (far - near)) / ((far / (far - near)) - z'')