光线投射公式
从相机发出一条光线,穿过与相机距离为1的屏幕上的某点,已知相机参数和点在屏幕空间上的位置(sx,sy)
,计算世界空间中投影到该点的对应点的坐标的公式为:
P=ViewMat−1∗ProjMat−1∗((sx,sy,1,1)∗farClip).
使用下面的公式得到的结果实际上是一样的。 P=ViewMat−1∗ProjMat−1∗(sx,sy,1,1), 但是需要对向量进行规范化,即:
P=[p.x,p.y,p.z,p.w]/p.w.
证明
投影公式ProjMat
为: P=⎣⎡Atan(FOV/2)10000tan(FOV/2)10000f−nf100f−n−fn0⎦⎤.
因为ViewMat
是齐次矩阵,不修改w,所以只考虑投影公式。首先计算它的逆。
因为左下角与右上角为0,可以视为2×2的分块矩阵,计算逆时只需要计算右下角的逆即可。左上角为对角矩阵,逆是对角元素的倒数。2维矩阵较小,可以用伴随矩阵计算逆。伴随矩阵公式为:
adj([acbd])=[d−c−ba]. 关于n×n矩阵A,有 Aadj(A)=adj(A)A=det(A)I. 即 A−1=det(A)−1adj(A) 令 A=[f−nf1f−n−fn0]
则 det(A)=f−nfn.A−1=f−nfn1[0−1f−nfnf−nf]=[0−fnf−n1n1] 因此投影矩阵的逆为: P−1=⎣⎡Atan(FOV/2)0000tan(FOV/2)00000−fnf−n001n1⎦⎤ 根据公式: ⎣⎡sxsy11⎦⎤×farClip=⎣⎡sx×farClipsy×farClipfarClipfarClip⎦⎤, P−1⎣⎡sx×farClipsy×farClipfarClipfarClip⎦⎤=⎣⎡Atan(FOV/2)sx×farCliptan(FOV/2)sy×farClipfarClip1⎦⎤ 对比直接相乘的结果: P−1⎣⎡sxsy11⎦⎤=⎣⎡Atan(FOV/2)sxtan(FOV/2)sy11⎦⎤=⎣⎡Atan(FOV/2)sxtan(FOV/2)sy1f1⎦⎤
可以看出,无论乘不乘farClip
规范化后的结果确实是一样的。但是因为glm并没有提供我们需要的规范化的函数,所以通过乘farClip
来省去手动规范化的步骤是可以提高效率的。
预览: