Direct3D中投影和未投影Z值之间的关系

时间:2014-03-12 09:27:02

标签: c# vector direct3d projection

我一直试图想出这种关系,但我不能,也许我只是不寻找正确的事情。如果我使用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

1 个答案:

答案 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'')