正交投影矩阵的视锥体是一个长方体 [ l , r ] [ b , t ] [ f , n ] [l,r][b,t][f,n] [l,r][b,t][f,n],我们要把这个长方体转换到一个正方体 [ ? 1 , 1 ] [ ? 1 , 1 ] [ ? 1 , 1 ] [-1,1][-1,1][-1,1] [?1,1][?1,1][?1,1]中,如下图所示
第一步为平移,计算出长方体的中心点为
[
(
l
+
r
)
/
2
,
(
b
+
t
)
/
2
,
(
f
+
n
)
/
2
]
[(l+r)/2,(b+t)/2,(f+n)/2]
[(l+r)/2,(b+t)/2,(f+n)/2],然后将中心点移动到原点,矩阵为
M
t
r
a
n
s
l
a
t
e
=
[
1
0
0
?
(
l
+
r
)
/
2
0
1
0
?
(
b
+
t
)
/
2
0
0
1
?
(
f
+
n
)
/
2
0
0
0
1
]
\mathbf M_{translate} = \begin{bmatrix} 1 & 0 & 0 & -(l+r)/2 \\ 0 & 1 & 0 & -(b+t)/2 \\ 0 & 0 & 1 & -(f+n)/2 \\ 0 & 0 & 0 & 1 \end{bmatrix}
Mtranslate?=
?1000?0100?0010??(l+r)/2?(b+t)/2?(f+n)/21?
?
第二步为缩放,例如从
[
l
,
r
]
[l,r]
[l,r]缩放到
[
?
1
,
1
]
[-1,1]
[?1,1],缩放系数为
2
/
(
r
?
l
)
2/(r-l)
2/(r?l),所以矩阵为
M
s
c
a
l
e
=
[
2
/
(
r
?
l
)
0
0
0
0
2
/
(
t
?
b
)
0
0
0
0
2
/
(
n
?
f
)
0
0
0
0
0
]
\mathbf M_{scale} = \begin{bmatrix} 2/(r-l) & 0 & 0 & 0 \\ 0 & 2/(t-b) & 0 & 0 \\ 0 & 0 & 2/(n-f) & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix}
Mscale?=
?2/(r?l)000?02/(t?b)00?002/(n?f)0?0000?
?
综上,正交投影矩阵为
M
o
r
t
h
o
=
M
s
c
a
l
e
?
M
t
r
a
n
s
l
a
t
e
\mathbf M_{ortho} = \mathbf M_{scale} * \mathbf M_{translate}
Mortho?=Mscale??Mtranslate?
透视投影矩阵的视锥体是一个四棱锥的一部分,其中近平面为
z
=
n
z=n
z=n,远平面为
z
=
f
z=f
z=f,我们要把这个视锥体转换到一个正方体
[
?
1
,
1
]
[
?
1
,
1
]
[
?
1
,
1
]
[-1,1][-1,1][-1,1]
[?1,1][?1,1][?1,1]中,可以先把远平面压缩,把视锥体压缩成一个长方体,然后再通过正交投影矩阵就可以变换到正方体中,如图。
我们定义视锥体压缩的矩阵为 M p e r s p ? > o r t h o \mathbf M_{persp->ortho} Mpersp?>ortho?,在把视锥体压缩成长方体的过程中,我们规定三个原则
首先,设
M
p
e
r
s
p
?
>
o
r
t
h
o
\mathbf M_{persp->ortho}
Mpersp?>ortho?为如下式子,先将所有元素设为未知数:
M
p
e
r
s
p
?
>
o
r
t
h
o
=
[
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
]
\mathbf M_{persp->ortho} = \begin{bmatrix} A & B & C & D \\ E & F & G & H \\ I & J & K & L \\ M & N & O & P \\ \end{bmatrix}
Mpersp?>ortho?=
?AEIM?BFJN?CGKO?DHLP?
?
对于视锥体内的任意一点
(
x
,
y
,
z
)
(x,y,z)
(x,y,z),压缩以后的
x
,
y
x,y
x,y坐标应该与近平面上对应的点相同,如下图所示,根据三角形的相似关系,我们可以得到
x
,
=
n
x
/
z
,
y
,
=
n
y
/
z
x^, = nx/z, y^, = ny/z
x,=nx/z,y,=ny/z。
因此对于齐次坐标表示的
(
x
,
y
,
z
,
1
)
(x,y,z,1)
(x,y,z,1)一点,它在视锥体压缩后的坐标为
(
n
x
/
z
,
n
y
/
z
,
u
n
k
n
o
w
,
1
)
(nx/z,ny/z,unknow,1)
(nx/z,ny/z,unknow,1),这里我们新的
z
,
z^,
z,值还不知道,暂不讨论。为了便于后续的计算,压缩后的坐标为
(
n
x
,
n
y
,
u
n
k
n
o
w
,
z
)
(nx,ny,unknow,z)
(nx,ny,unknow,z)。我们有下面的式子:
M
p
e
r
s
p
?
>
o
r
t
h
o
?
[
x
y
z
1
]
=
[
n
x
n
y
u
n
k
n
o
w
n
z
]
\mathbf M_{persp->ortho} \cdot \begin{bmatrix} x\\ y\\ z\\ 1 \end{bmatrix} = \begin{bmatrix} nx\\ ny\\ unknown\\ z \end{bmatrix}
Mpersp?>ortho??
?xyz1?
?=
?nxnyunknownz?
?
将式子展开,我们有:
A
x
+
B
y
+
C
z
+
D
=
n
x
E
x
+
F
y
+
G
z
+
H
=
n
y
M
x
+
N
y
+
O
z
+
P
=
z
Ax + By + Cz + D = nx\\ Ex + Fy + Gz + H = ny\\ Mx + Ny + Oz + P = z
Ax+By+Cz+D=nxEx+Fy+Gz+H=nyMx+Ny+Oz+P=z
可知:
A
=
n
,
B
=
0
,
C
=
0
,
D
=
0
E
=
0
,
F
=
n
,
G
=
0
,
H
=
0
M
=
0
,
N
=
0
,
O
=
1
,
P
=
0
A = n,B = 0,C = 0,D = 0\\ E = 0,F = n,G = 0,H = 0\\ M = 0,N = 0, O = 1, P = 0
A=n,B=0,C=0,D=0E=0,F=n,G=0,H=0M=0,N=0,O=1,P=0
这时,我们知晓了矩阵中12个位置数的值,此时的矩阵如下,还剩
I
,
J
,
K
,
L
I,J,K,L
I,J,K,L四个未知数。
M
p
e
r
s
p
?
>
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
I
J
K
L
0
0
1
0
]
\mathbf M_{persp->ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ I & J & K & L\\ 0 & 0 & 1 & 0 \end{bmatrix}
Mpersp?>ortho?=
?n0I0?0nJ0?00K1?00L0?
?
接下来考虑三原则中第一个原则,近平面的所有点坐标不变。对于近平面上的一点
(
x
,
y
,
n
,
1
)
(x,y,n,1)
(x,y,n,1),有下式:
[
n
0
0
0
0
n
0
0
I
J
K
L
0
0
1
0
]
?
[
x
y
n
1
]
=
[
n
x
n
y
n
?
n
n
]
\begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ I & J & K & L\\ 0 & 0 & 1 & 0\\ \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ n\\ 1 \end{bmatrix} = \begin{bmatrix} nx\\ ny\\ n*n\\ n \end{bmatrix}
?n0I0?0nJ0?00K1?00L0?
??
?xyn1?
?=
?nxnyn?nn?
?
其中后式是为了配平方程,我们将齐次坐标
(
x
,
y
,
z
,
1
)
(x,y,z,1)
(x,y,z,1)等价变为
(
n
x
,
n
y
,
n
?
n
,
n
)
(nx,ny,n*n,n)
(nx,ny,n?n,n)。
根据矩阵的第三行展开计算,可以得到
I
x
+
J
y
+
K
n
+
L
=
n
?
n
Ix + Jy + Kn+L = n*n\\
Ix+Jy+Kn+L=n?n
于是有
I = 0 , J = 0 K n + L = n ? n \begin{align} I = 0,J = 0 \nonumber \\ Kn + L = n * n \\ \end{align} I=0,J=0Kn+L=n?n??
此时矩阵如下,还剩
K
,
L
K,L
K,L两个未知数。
M
p
e
r
s
p
?
>
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
0
0
K
L
0
0
1
0
]
\mathbf M_{persp->ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & K & L\\ 0 & 0 & 1 & 0 \end{bmatrix}
Mpersp?>ortho?=
?n000?0n00?00K1?00L0?
?
最后考虑三原则中第三个原则,远平面的中心点坐标值不变,为
(
0
,
0
,
f
,
1
)
(0,0,f,1)
(0,0,f,1)。我们有下式:
[
n
0
0
0
0
n
0
0
0
0
K
L
0
0
1
0
]
?
[
0
0
f
1
]
=
[
0
0
f
?
f
f
]
\begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & K & L\\ 0 & 0 & 1 & 0\\ \end{bmatrix} \cdot \begin{bmatrix} 0\\ 0\\ f\\ 1 \end{bmatrix} = \begin{bmatrix} 0\\ 0\\ f*f\\ f \end{bmatrix}
?n000?0n00?00K1?00L0?
??
?00f1?
?=
?00f?ff?
?
后式同样是为了配平方程,我们将齐次坐标
(
0
,
0
,
f
,
1
)
(0,0,f,1)
(0,0,f,1)等价变为
(
0
,
0
,
f
?
f
,
f
)
(0,0,f*f,f)
(0,0,f?f,f)。
根据矩阵的第三行展开计算,可以得到
K
f
+
L
=
f
?
f
\begin{align} Kf + L = f*f \end{align}
Kf+L=f?f??
联立
(
1
)
(
2
)
(1)(2)
(1)(2)两式,我们最终能够解得
K
=
n
+
f
L
=
?
n
f
K = n + f\\ L = -nf
K=n+fL=?nf
此时,我们终于求得了
M
p
e
r
s
p
?
>
o
r
t
h
o
\mathbf M_{persp->ortho}
Mpersp?>ortho?矩阵
M
p
e
r
s
p
?
>
o
r
t
h
o
=
[
n
0
0
0
0
n
0
0
0
0
n
+
f
?
n
f
0
0
1
0
]
\mathbf M_{persp->ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix}
Mpersp?>ortho?=
?n000?0n00?00n+f1?00?nf0?
?
乘上正交投影矩阵
M
o
r
t
h
o
\mathbf M_{ortho}
Mortho?,我们便可以得到透视投影矩阵
M
p
e
r
s
p
\mathbf M_{persp}
Mpersp?
M
p
e
r
s
p
=
M
o
r
t
h
o
?
M
p
e
r
s
p
?
>
o
r
t
h
o
=
[
2
/
(
r
?
l
)
0
0
0
0
2
/
(
t
?
b
)
0
0
0
0
2
/
(
n
?
f
)
0
0
0
0
0
]
?
[
1
0
0
?
(
l
+
r
)
/
2
0
1
0
?
(
b
+
t
)
/
2
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
]
\mathbf M_{persp} = \mathbf M_{ortho} \cdot \mathbf M_{persp->ortho} =\\ \begin{bmatrix} 2/(r-l) & 0 & 0 & 0 \\ 0 & 2/(t-b) & 0 & 0 \\ 0 & 0 & 2/(n-f) & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix} \cdot \begin{bmatrix} 1 & 0 & 0 & -(l+r)/2 \\ 0 & 1 & 0 & -(b+t)/2 \\ 0 & 0 & 1 & -(f+n)/2 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix}
Mpersp?=Mortho??Mpersp?>ortho?=
?2/(r?l)000?02/(t?b)00?002/(n?f)0?0000?
??
?1000?0100?0010??(l+r)/2?(b+t)/2?(f+n)/21?
??
?n000?0n00?00n+f1?00?nf0?
?
透视矩阵一般是由 f o v , a s p e c t , f a r , n e a r fov,aspect,far,near fov,aspect,far,near四个参数定义的,我们尝试用这四个参数来表示上式中的 n , f , t , b , r , l n,f,t,b,r,l n,f,t,b,r,l六个参数。其中 f o v fov fov表示视场角, a s p e c t aspect aspect表示宽高比, f a r , n e a r far,near far,near分别表示远平面和近平面。
易知,
n
=
n
e
a
r
,
f
=
f
a
r
n = near,f = far
n=near,f=far。
根据上图的三角关系,我们有
t
=
n
e
a
r
?
t
a
n
(
f
o
v
2
)
,
b
=
?
n
e
a
r
?
t
a
n
(
f
o
v
2
)
r
=
a
s
p
e
c
t
?
n
e
a
r
?
t
a
n
(
f
o
v
2
)
,
l
=
?
a
s
p
e
c
t
?
n
e
a
r
?
t
a
n
(
f
o
v
2
)
t = near * tan(\frac{fov}{2}),b = -near * tan(\frac{fov}{2})\\ r = aspect * near * tan(\frac{fov}{2}), l = -aspect * near * tan(\frac{fov}{2})
t=near?tan(2fov?),b=?near?tan(2fov?)r=aspect?near?tan(2fov?),l=?aspect?near?tan(2fov?)
最终,我们得到的透视投影矩阵为
M
p
e
r
s
p
=
[
c
o
t
(
f
o
v
)
2
?
a
s
p
e
c
t
?
n
e
a
r
0
0
0
0
c
o
t
(
f
o
v
)
2
0
0
0
0
n
e
a
r
+
f
a
r
n
e
a
r
?
f
a
r
?
2
?
n
e
a
r
?
f
a
r
n
e
a
r
?
f
a
r
0
0
1
0
]
\mathbf M_{persp} = \begin{bmatrix} \frac{cot(fov)}{2*aspect*near} & 0 & 0 & 0\\ 0 & \frac{cot(fov)}{2} & 0 & 0\\ 0 & 0 & \frac{near+far}{near-far} & -\frac{2*near*far}{near-far}\\ 0 & 0 & 1 & 0 \end{bmatrix}
Mpersp?=
?2?aspect?nearcot(fov)?000?02cot(fov)?00?00near?farnear+far?1?00?near?far2?near?far?0?
?
https://zhuanlan.zhihu.com/p/122411512