透视投影矩阵推导步骤及各组成矩阵作用解析
我太懂这种研究很久还是摸不透的感觉了——透视投影矩阵的构造看似复杂,其实是把几个线性变换模块拼起来的,咱们拆成一个个矩阵来看就清晰多了。
核心思路:把锥形视锥体“变”成标准正方体
透视投影的本质是把相机空间里的透视视锥体(近小远大的锥形空间,只有这个区域内的物体才会被渲染),最终映射到**标准设备坐标(NDC)**的[-1,1]³正方体里。这个过程需要两个关键矩阵,再把它们相乘得到最终的透视投影矩阵。
1. 透视挤压矩阵:把锥形压成长方体
这个矩阵是解决透视投影“近大远小”问题的核心,作用是把相机空间的锥形视锥体,挤压成一个轴对齐的长方体(这样后续就能用简单的正交投影处理了)。
它的原理基于相似三角形:相机在原点,远处的物体在屏幕上的投影会比近处的小,我们可以利用齐次坐标的特性,把x、y坐标和深度z绑定,让后续的透视除法(除以齐次分量w)自动完成缩放。
对于右手坐标系(相机在原点,看向-z方向,近平面z=-n,远平面z=-f),这个矩阵的形式是:
[ n/r 0 0 0 ] [ 0 n/t 0 0 ] [ 0 0 -(f+n)/(f-n) -2fn/(f-n) ] [ 0 0 -1 0 ]
(注:这里r是近平面右边界,t是上边界;如果是用左l、右r、下b、上t的参数,第一行是2n/(r-l),第三项是(r+l)/(r-l),本质是一样的,只是参数定义不同)
简单来说,这个矩阵做了三件事:
- 把x、y方向的坐标按深度z缩放,模拟透视收缩
- 把z轴的深度值从[−n, −f]映射到一个便于后续正交变换的范围
- 把齐次分量w设置为−z,为之后的透视除法做准备
2. 正交投影矩阵:把长方体塞进标准正方体
当锥形被压成长方体后,接下来就用正交投影矩阵把这个长方体缩放+平移到NDC的[-1,1]³空间里——这一步是纯粹的线性变换,没有透视的非线性特性。
同样基于右手坐标系,正交投影矩阵的形式是:
[ 1/r 0 0 -(r+l)/(2r) ] [ 0 1/t 0 -(t+b)/(2t) ] [ 0 0 -2/(f-n) -(f+n)/(f-n) ] [ 0 0 0 1 ]
它的核心作用就是:
- 把x轴从[l, r]缩放到[-1, 1]
- 把y轴从[b, t]缩放到[-1, 1]
- 把z轴从[−n, −f]缩放到[-1, 1]
- 把长方体的中心平移到NDC的原点
最终透视投影矩阵:两个矩阵相乘
因为图形学里用的是列向量,变换的顺序是从右到左,所以最终的透视投影矩阵 = 正交投影矩阵 × 透视挤压矩阵。
把两个矩阵相乘后,就能得到我们平时在OpenGL、DirectX里用到的标准透视投影矩阵了。举个例子,用左l、右r、下b、上t、近n、远f的通用参数,最终矩阵的形式是:
[ 2n/(r-l) 0 (r+l)/(r-l) 0 ] [ 0 2n/(t-b) (t+b)/(t-b) 0 ] [ 0 0 -(f+n)/(f-n) -2fn/(f-n) ] [ 0 0 -1 0 ]
其实你可以把整个过程想象成:先把锥形的橡皮泥捏成规整的长方体,再把这个长方体按比例缩小、移动,塞进一个边长为2的标准正方体里——每个矩阵就是其中一步的“工具”。
内容的提问来源于stack exchange,提问作者Manh Nguyen Huu

