Games101学习笔记
第一部分:矩阵与变换
文章目录
齐次坐标
为了将坐标的平移、旋转、缩放、投影等变换写成 A = M × B A = M \times B A=M×B的形式,我们将空间(或平面)上点与向量的坐标扩展成如下形式:
- 点: P = ( x , y , z , 1 ) P = (x,y,z,1) P=(x,y,z,1)
- 向量: v ⃗ = ( x , y , z , 0 ) \vec{v} = (x,y,z,0) v=(x,y,z,0)
其中点的坐标也可写为 ( x , y , z , w ) (x,y,z,w) (x,y,z,w),表示的点为 ( x / w , y / w , z / w , 1 ) (x/w,y/w,z/w,1) (x/w,y/w,z/w,1)(显然要求 w ≠ 0 w \ne 0 w=0)。
MVP变换
所谓MVP变换即在图形学中常用的Model、View、Projection变换。
如图,计算机内的物体要想显示到屏幕上,需要经历以下几个变换:
- modeling transformation:
将物体模型变换到某个世界坐标(world space)中去。 - camera transformation:
对所有物体进行一次变换,使得其上每个点的坐标 P P P变为以摄像机为新坐标系下的坐标 P ′ {P}' P′ - projection transformation:
将摄像机视锥中的物体进行变换,达到近大远小的效果。 - viewport transformation:
将经过上述变换的物体投影到2D平面上进行显示。
Model变换
Model变换包含平移、旋转、缩放等操作。对于不同的物体,因为导入时的初始位置和在世界中放置的位置不同,相对应的Model变换也不相同。
我们可以将Model变换拆解成三种变换的组合(以3D为例):
缩放
s c a l e = [ s 0 0 0 0 s 0 0 0 0 s 0 0 0 0 1 ] scale=\begin{bmatrix}{s} & {0} & {0} & {0} \\ {0} & {s} & {0} & {0} \\ {0} & {0} & {s} & {0} \\ {0} & {0} & {0} & {1}\end{bmatrix} scale=⎣⎢⎢⎡s0000s0000s00001⎦⎥⎥⎤
平移
t r a n s l a t i o n = [ 0 0 0 t x 0 0 0 t y 0 0 0 t z 0 0 0 1 ] translation=\begin{bmatrix}{}{0} & {0} & {0} & {t_x} \\ {0} & {0} & {0} & {t_y} \\ {0} & {0} & {0} & {t_z} \\ {0} & {0} & {0} & {1}\end{bmatrix} translation=⎣⎢⎢⎡000000000000txtytz1⎦⎥⎥⎤
旋转(逆时针)
x轴
R x ( α ) = [ 1 0 0 0 0 cos ( α ) − sin ( α ) 0 0 sin ( α ) cos ( α ) 0 0 0 0 1 ] R_x(\alpha)=\begin{bmatrix}{}{1} & {0} & {0} & {0} \\ {0} & {\cos(\alpha)} & {-\sin(\alpha)} & {0} \\ {0} & {\sin(\alpha)} & {\cos(\alpha)} & {0} \\ {0} & {0} & {0} & {1}\end{bmatrix} Rx(α)=⎣⎢⎢⎡10000cos(α)sin(α)00−sin(α)cos(α)00001⎦⎥⎥⎤
y轴
R y ( α ) = [ cos ( α ) 0 sin ( α ) 0 0 1 0 0 − sin ( α ) 0 cos ( α ) 0 0 0 0 1 ] R_y(\alpha)=\begin{bmatrix}{}{\cos(\alpha)} & {0} & {\sin(\alpha)} & {0} \\ {0} & {1} & {0} & {0} \\ {-\sin(\alpha)} & {0} & {\cos(\alpha)} & {0} \\ {0} & {0} & {0} & {1}\end{bmatrix} Ry(α)=⎣⎢⎢⎡cos(α)0−sin(α)00100sin(α)0cos(α)00001⎦⎥⎥⎤
z轴
R z ( α ) = [ cos ( α ) − sin ( α ) 0 0 sin ( α ) cos ( α ) 0 0 0 0 1 0 0 0 0 1 ] R_z(\alpha)=\begin{bmatrix}{}{\cos(\alpha)} & {-\sin(\alpha)} & {0} & {0} \\ {\sin(\alpha)} & {\cos(\alpha)} & {0} & {0} \\ {0} & {0} & {1} & {0} \\ {0} & {0} & {0} & {1}\end{bmatrix} Rz(α)=⎣⎢⎢⎡cos(α)sin(α)00−sin(α)cos(α)0000100001⎦⎥⎥⎤
任意过原点的轴 n ⃗ \vec{n} n
R ( n ⃗ , α ) = cos α I ⃗ + ( 1 − cos α ) n ⃗ n T ⃗ + sin α [ 0 − n z n y n z 0 − n x − n y n x 0 ] R(\vec{n},\alpha) = \cos\alpha\vec{I} + (1-\cos\alpha)\vec{n}\vec{n^T}+\sin\alpha\begin{bmatrix}0 & -n_z & n_y\\n_z & 0 & -n_x\\-n_y & n_x & 0\end{bmatrix} R(n,α)=cosαI+(1−cosα)nnT+sinα⎣⎡0nz−ny−nz0nxny−nx0⎦⎤
M m o d e l M_{model} Mmodel矩阵由上述一个或多个矩阵复合(相乘)得到,注意矩阵相乘时实际变换顺序是从右到左。
Camera变换
一般将camera放置在世界坐标的原点,并且令其 g ⃗ \vec{g} g(gaze)方向与 − z -z −z轴重合, t ⃗ \vec{t} t(top)方向与 + y +y +y轴重合。故camera变换一般分为两步:
- 用平移变换将camera移动到原点。
- 通过旋转变换令两者坐标系重合。
利用逆变换思想可以写出如下方程:
M
c
a
m
=
[
u
v
w
e
0
0
0
1
]
−
1
=
[
x
u
y
u
z
u
0
x
v
y
v
z
v
0
x
w
y
w
z
w
0
0
0
0
1
]
[
1
0
0
−
x
e
0
1
0
−
y
e
0
0
1
−
z
e
0
0
0
1
]
M_{cam}=\begin{bmatrix}\mathbf{u}&\mathbf{v}&\mathbf{w}&\mathbf{e}\\0&0&0&1\end{bmatrix}^{-1} = \begin{bmatrix}x_u&y_u&z_u&0\\x_v&y_v&z_v&0\\x_w&y_w&z_w&0\\0&0&0&1\end{bmatrix}\begin{bmatrix}1&0&0&-x_e\\0&1&0&-y_e\\0&0&1&-z_e\\0&0&0&1\end{bmatrix}
Mcam=[u0v0w0e1]−1=⎣⎢⎢⎡xuxvxw0yuyvyw0zuzvzw00001⎦⎥⎥⎤⎣⎢⎢⎡100001000010−xe−ye−ze1⎦⎥⎥⎤
其中用到了旋转矩阵是正交矩阵的性质,即
A
T
=
A
−
1
A^T=A^{-1}
AT=A−1
当用户或玩家移动自身位置、调整视口角度的时候,显示出的物体会实时变化,此变化即为
M
c
a
m
M_{cam}
Mcam矩阵改变并应用在所有物体上的结果。
实际上,当camera移动时,物体的坐标乘以
M
c
a
m
M_{cam}
Mcam矩阵之后改变的是物体的位置,可以理解为camera不动,所有的物体在向着指令相反的方向运动,导致在camera坐标系下观察像是自己在运动。
Projection变换
正交投影变换
为了后续viewport transformation的方便,我们需要把需要显示的部分用一个长方体包围起来,并将其压缩到以原点为几何中心,边长为2的正方体中。
运用平移和缩放变换,容易写出以下式子:
M
o
r
t
h
=
[
2
r
−
l
0
0
−
r
+
l
r
−
l
0
2
t
−
b
0
−
t
+
b
t
−
b
0
0
2
n
−
f
−
n
+
f
n
−
f
0
0
0
1
]
M_{orth}=\begin{bmatrix}\frac{2}{r-l}&0&0&-\frac{r+l}{r-l}\\0&\frac{2}{t-b}&0&-\frac{t+b}{t-b}\\0&0&\frac{2}{n-f}&-\frac{n+f}{n-f}\\0&0&0&1\end{bmatrix}
Morth=⎣⎢⎢⎡r−l20000t−b20000n−f20−r−lr+l−t−bt+b−n−fn+f1⎦⎥⎥⎤
透视投影变换
如图,现实世界中我们的视野呈锥体状而非正交投影认为的长方体状,故透视投影看到的东西要比正交投影看到的东西多(越远物体越小,看到的物体数量越多)。
所以,要想在正交投影的基础上实现透视投影,就需要把透视投影可视部分多出来的那一块“压”进正交投影可视部分中去,然后再进行正交投影。
大致求解 M p e r s p → o r t h o M_{persp\rightarrow ortho} Mpersp→ortho过程如下。
最终
M
p
e
r
s
p
=
M
o
r
t
h
o
M
p
e
r
s
p
→
o
r
t
h
o
M_{persp}=M_{ortho}M_{persp\rightarrow ortho}
Mpersp=MorthoMpersp→ortho
(其中
M
o
r
t
h
o
M_{ortho}
Mortho中的参数与视角
θ
\theta
θ以及屏幕长宽比
ω
\omega
ω有关。)
Viewport变换
Viewport变换也称为视口变换,是将经过MVP变换后的可视部分(位于 [ − 1 , 1 ] 3 [-1,1]^3 [−1,1]3内)转换到2D屏幕所在范围内( [ 0 , w i d t h ] ∗ [ 0 , h e i g h t ] [0,width] * [0,height] [0,width]∗[0,height])。
即将位于原点的标准立方体先拉伸,再平移。得:
M
v
i
e
w
p
o
r
t
=
[
w
i
d
t
h
2
0
0
w
i
d
t
h
2
0
h
e
i
g
h
t
2
0
h
e
i
g
h
t
2
0
0
1
0
0
0
0
1
]
M_{viewport}=\begin{bmatrix}\frac{width}{2}&0&0&\frac{width}{2}\\0&\frac{height}{2}&0&\frac{height}{2}\\0&0&1&0\\0&0&0&1\end{bmatrix}
Mviewport=⎣⎢⎢⎡2width00002height0000102width2height01⎦⎥⎥⎤