前提条件:右手系坐标,目标将视锥体内的坐标压缩为x,y,z->[-1,1]
下面开始推导
第一步:把x,y方向上的点压缩,也即如下图所示的把视锥体压缩成长方体
P压缩后的点为 P ′ ( x ′ , y ′ , z ′ ) P'(x',y',z') P′(x′,y′,z′).则根据相似定律, y z = y ′ − n , x z = x ′ − n \frac{y}{z}=\frac{y'}{-n},\frac{x}{z}=\frac{x'}{-n} zy=−ny′,zx=−nx′
故有
y ′ = − n y / z , x ′ = − n x / z ; y'=-{{ny}\Bigg/{z}},x'=-{{nx}\Bigg/{z}}; y′=−ny/z,x′=−nx/z;
现在我们可以推导压缩矩阵 M t \boldsymbol{M}_{\boldsymbol{t}} Mt,将x’,y’替换为x,y,z的表达式.
[ ] [ x y z 1 ] = [ x ′ y ′ z ′ 1 ] = [ − n x / z − n y / z z ′ 1 ] \\ \left[ \begin{matrix} & & & \\ & & & \\ & & & \\ & & & \\ \end{matrix} \right] \left[ \begin{array}{c} x\\ y\\ z\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} x'\\ y'\\ z'\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} {{-nx}\Bigg/{z}}\\ -{{ny}\Bigg/{z}}\\ z'\\ 1\\ \end{array} \right] \\ ⎣ ⎡⎦ ⎤⎣ ⎡xyz1⎦ ⎤=⎣ ⎡x′y′z′1⎦ ⎤=⎣ ⎡−nx/z−ny/zz′1⎦ ⎤
可以同乘z消除分子,接下来可以推出压缩矩阵的1,2,4行
[ ] [ x y z 1 ] = [ n x n y ? − z ] ⟶ [ n 0 0 0 0 n 0 0 0 0 − 1 0 ] [ x y z 1 ] = [ n x n y ? − z ] \left[ \begin{matrix} & & & \\ & & & \\ & & & \\ & & & \\ \end{matrix} \right] \left[ \begin{array}{c} x\\ y\\ z\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} nx\\ ny\\ ?\\ -z\\ \end{array} \right] \longrightarrow \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ & & & \\ 0& 0& -1& 0\\ \end{matrix} \right] \left[ \begin{array}{c} x\\ y\\ z\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} nx\\ ny\\ ?\\ -z\\ \end{array} \right] \\ ⎣ ⎡⎦ ⎤⎣ ⎡xyz1⎦ ⎤=⎣ ⎡nxny?−z⎦ ⎤⟶⎣ ⎡n000n000−1000⎦ ⎤⎣ ⎡xyz1⎦ ⎤=⎣ ⎡nxny?−z⎦ ⎤
接下来观察压缩后的长方体,可以发现(0,0,-n)和(0,0,-f)点压缩后坐标不变故有
[ 0 0 − n 1 ] 和 [ 0 0 − f 1 ] [ n 0 0 0 0 n 0 0 0 0 A B 0 0 − 1 0 ] [ 0 0 − n 1 ] = [ 0 0 − A n + B n ] = [ 0 0 − n n n ] , n 2 = A n − B [ n 0 0 0 0 n 0 0 0 0 A B 0 0 − 1 0 ] [ 0 0 − f 1 ] = [ 0 0 − A f + B f ] = [ 0 0 − f f f ] , f 2 = A f − B 解得 A = n + f , B = n f , \left[ \begin{array}{c} 0\\ 0\\ -n\\ 1\\ \end{array} \right] \text{和}\left[ \begin{array}{c} 0\\ 0\\ -f\\ 1\\ \end{array} \right] \\ \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& A& B\\ 0& 0& -1& 0\\ \end{matrix} \right] \left[ \begin{array}{c} 0\\ 0\\ -n\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} 0\\ 0\\ -An+B\\ n\\ \end{array} \right] =\left[ \begin{array}{c} 0\\ 0\\ -nn\\ n\\ \end{array} \right] ,n^2=An-B \\ \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& A& B\\ 0& 0& -1& 0\\ \end{matrix} \right] \left[ \begin{array}{c} 0\\ 0\\ -f\\ 1\\ \end{array} \right] =\left[ \begin{array}{c} 0\\ 0\\ -Af+B\\ f\\ \end{array} \right] =\left[ \begin{array}{c} 0\\ 0\\ -ff\\ f\\ \end{array} \right] ,f^2=Af-B \\ \text{解得}A=n+f,B=nf, \\ ⎣ ⎡00−n1⎦ ⎤和⎣ ⎡00−f1⎦ ⎤⎣ ⎡n0000n0000A−100B0⎦ ⎤⎣ ⎡00−n1⎦ ⎤=⎣ ⎡00−An+Bn⎦ ⎤=⎣ ⎡00−nnn⎦ ⎤,n2=An−B⎣ ⎡n0000n0000A−100B0⎦ ⎤⎣ ⎡00−f1⎦ ⎤=⎣ ⎡00−Af+Bf⎦ ⎤=⎣ ⎡00−fff⎦ ⎤,f2=Af−B解得A=n+f,B=nf,
故此矩阵
[ n 0 0 0 0 n 0 0 0 0 n + f n f 0 0 − 1 0 ] , 即为压缩矩阵, 接下来右乘平移矩阵把长方体中心移动到原点,再右乘缩放矩阵,将长方体变成2*2*2, [ 2 n ∗ tan ∗ a s p e c t 0 0 0 0 2 n ∗ tan 0 0 0 0 2 f − n 0 0 0 0 1 ] , \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& n+f& nf\\ 0& 0& -1& 0\\ \end{matrix} \right] ,\text{即为压缩矩阵,} \\ \text{接下来右乘平移矩阵把长方体中心移动到原点,再右乘缩放矩阵,将长方体变成2*2*2,} \\ \left[ \begin{matrix} \frac{2}{n*\tan *aspect}& 0& 0& 0\\ 0& \frac{2}{n*\tan}& 0& 0\\ 0& 0& \frac{2}{f-n}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] , \\ ⎣ ⎡n0000n0000n+f−100nf0⎦ ⎤,即为压缩矩阵,接下来右乘平移矩阵把长方体中心移动到原点,再右乘缩放矩阵,将长方体变成2*2*2,⎣ ⎡n∗tan∗aspect20000n∗tan20000f−n200001⎦ ⎤,
[ 1 n ∗ tan ∗ a s p e c t 0 0 0 0 1 n ∗ tan 0 0 0 0 2 n − f 0 0 0 0 1 ] [ 1 0 0 0 0 1 0 0 0 0 1 f + n 2 0 0 0 1 ] [ n 0 0 0 0 n 0 0 0 0 n + f n f 0 0 − 1 0 ] = [ 1 n ∗ tan ∗ a s p e c t 0 0 0 0 1 n ∗ tan 0 0 0 0 2 n − f 0 0 0 0 1 ] [ n 0 0 0 0 n 0 0 0 0 f + n 2 n f 0 0 − 1 0 ] = [ 1 tan ∗ a s p e c t 0 0 0 0 1 tan 0 0 0 0 − f + n f − n − 2 n f f − n 0 0 − 1 0 ] \left[ \begin{matrix} \frac{1}{n*\tan *aspect}& 0& 0& 0\\ 0& \frac{1}{n*\tan}& 0& 0\\ 0& 0& \frac{2}{n-f}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] \left[ \begin{matrix} 1& 0& 0& 0\\ 0& 1& 0& 0\\ 0& 0& 1& \frac{f+n}{2}\\ 0& 0& 0& 1\\ \end{matrix} \right] \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& n+f& nf\\ 0& 0& -1& 0\\ \end{matrix} \right] \\ =\left[ \begin{matrix} \frac{1}{n*\tan *aspect}& 0& 0& 0\\ 0& \frac{1}{n*\tan}& 0& 0\\ 0& 0& \frac{2}{n-f}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right] \left[ \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& \frac{f+n}{2}& nf\\ 0& 0& -1& 0\\ \end{matrix} \right] =\left[ \begin{matrix} \frac{1}{\tan *aspect}& 0& 0& 0\\ 0& \frac{1}{\tan}& 0& 0\\ 0& 0& -\frac{f+n}{f-n}& -\frac{2nf}{f-n}\\ 0& 0& -1& 0\\ \end{matrix} \right] ⎣ ⎡n∗tan∗aspect10000n∗tan10000n−f200001⎦ ⎤⎣ ⎡100001000010002f+n1⎦ ⎤⎣ ⎡n0000n0000n+f−100nf0⎦ ⎤=⎣ ⎡n∗tan∗aspect10000n∗tan10000n−f200001⎦ ⎤⎣ ⎡n0000n00002f+n−100nf0⎦ ⎤=⎣ ⎡tan∗aspect10000tan10000−f−nf+n−100−f−n2nf0⎦ ⎤
这个最终的矩阵就是OpenGL的透视投影矩阵