MVP变换(games101)
0. M V P MVP MVP的用途
想像成相机,思考怎样拍照片(以拍摄物体为例)
- 首先调整好拍摄物体,对物体进行模型变换 ( M o d e l t r a n s f o r m a t i o n ) (Model transformation) (Modeltransformation)
- 放置好相机的位置上,调整好相机的拍摄角度 ( V i e w t r a n s f o r m a t i o n ) (View transformation) (Viewtransformation)
- 拍摄照片,实现3D物体变成2D图片 ( P r o j e c t i o n t r a n s f o r m a t i o n ) (Projection transformation) (Projectiontransformation)
1. M o d e l Model Model(模型变换)
顾名思义对模型进行一系列的平移旋转缩放达到目标物体场景,具体的实现见链接: 计算机图形学中的矩阵变化.
2. V i e w View View(视图变换)
视图变换所需参数
- 相机的位置上 e e e
- 相机的观察方向 g ( L o o k − a t ) g (Look-at ) g(Look−at)
- 相机的上方向 t ( U p d i r e c t i o n ) t(Up direction) t(Updirection)
- 相机的右方向 g × t g × t g×t
如图所示为相机的初始位置
把相机看作空间中的一个物体,若将相机和其他的物体同时进行移动(进行同一种的位移变换),那么其他的物体和相机就会是一种相对静止,只移动物体或者只移动Camera,最后可能都会得到同一个结果,这样约定相机并不移动,相机放在
(
0
,
0
,
0
)
(0,0,0)
(0,0,0)的位置,相机朝向也固定为指向
−
Z
-Z
−Z,这个位置为标准位置
这时我们所需要考虑的就是如何把相机移动到标准位置
具体做法如下:
- 先将相机的位置移动到原点 ( o r i g i n ) (origin) (origin)
- 将 g g g旋转到 − z -z −z轴方向
- 将 g × t g×t g×t旋转到x轴方向
- 将
g
×
t
g×t
g×t旋转到x轴方向
M v i e w M_{v i e w} Mview矩阵的具体实现:
将
M
v
i
e
w
M_{v i e w}
Mview矩阵分解为
R
v
i
e
w
R_{v i e w}
Rview和
T
v
i
e
w
T_{v i e w}
Tview两种变换矩阵,其中
T
v
i
e
w
T_{v i e w}
Tview为位移矩阵,将相机移动到原点,
R
v
i
e
w
R_{v i e w}
Rview为旋转矩阵,将相机沿着几个方向轴旋转到坐标系的位置。
M
view
=
R
view
T
view
M_{\text {view }}=R_{\text {view }} T_{\text {view }}
Mview =Rview Tview
T
v
i
e
w
T_{v i e w}
Tview矩阵,将相机移动到原点,即将
(
x
e
,
y
e
,
z
e
)
(xe,ye,ze)
(xe,ye,ze)移动到
(
0
,
0
,
0
)
(0,0,0)
(0,0,0),则
x
,
y
,
z
x,y,z
x,y,z上的位移量分别为
−
x
e
,
−
y
e
,
−
z
e
-xe,-ye,-ze
−xe,−ye,−ze。
T
v
i
e
w
=
[
1
0
0
−
x
e
0
1
0
−
y
e
0
0
1
−
z
e
0
0
0
1
]
T_{v i e w}=\left[\begin{array}{cccc}1 & 0 & 0 & -x_{e} \\ 0 & 1 & 0 & -y_{e} \\ 0 & 0 & 1 & -z_{e} \\ 0 & 0 & 0 & 1\end{array}\right]
Tview=⎣⎢⎢⎡100001000010−xe−ye−ze1⎦⎥⎥⎤
R
v
i
e
w
R_{v i e w}
Rview矩阵要做的事就是将
g
g
g旋转到
−
z
-z
−z轴,
t
t
t旋转到
Y
Y
Y轴,
(
g
×
t
)
(g × t)
(g×t)旋转到
x
x
x轴。如果这样直接旋转太麻烦,
−
z
-z
−z的方向向量为
(
0
,
0
,
−
1
)
,
y
(0,0,-1),y
(0,0,−1),y轴的方向向量为
(
0
,
1
,
0
)
(0,1,0)
(0,1,0),
x
x
x轴的方向向量为
(
1
,
0
,
0
)
(1,0,0)
(1,0,0),明显可以看出,从
−
z
-z
−z旋转到
g
g
g,从
y
y
y旋转到
t
t
t,从
x
x
x轴旋转到
(
g
×
t
)
(g×t)
(g×t)更为简单,这个旋转矩阵为:
R
v
i
e
w
=
[
x
g
^
×
t
^
y
g
^
×
t
^
z
g
^
×
t
^
0
x
t
y
t
z
t
0
x
−
g
y
−
g
z
−
g
0
0
0
0
1
]
R_{v i e w}=\left[\begin{array}{cccc}x_{\hat{g} \times \hat{t}} & y_{\hat{g} \times \hat{t}} & z_{\hat{g} \times \hat{t}} & 0 \\ x_{t} & y_{t} & z_{t} & 0 \\ x_{-g} & y_{-g} & z_{-g} & 0 \\ 0 & 0 & 0 & 1\end{array}\right]
Rview=⎣⎢⎢⎡xg^×t^xtx−g0yg^×t^yty−g0zg^×t^ztz−g00001⎦⎥⎥⎤
再求这个矩阵的逆矩阵,即逆变换,就可以得到相机的三个方向旋转到坐标系的三个轴的变换矩阵。因为旋转矩阵都是正交矩阵,所以其逆矩阵 = 转置矩阵。
R
view
−
1
=
[
x
g
^
×
t
^
x
t
x
−
g
0
y
g
^
×
t
^
y
t
y
−
g
0
z
g
^
×
t
^
z
t
z
−
g
0
0
0
0
1
]
R_{\text {view }}^{-1}=\left[\begin{array}{cccc}x_{\hat{g} \times \hat{t}} & x_{t} & x_{-g} & 0 \\ y_{\hat{g} \times \hat{t}} & y_{t} & y_{-g} & 0 \\ z_{\hat{g} \times \hat{t}} & z_{t} & z_{-g} & 0 \\ 0 & 0 & 0 & 1\end{array}\right]
Rview −1=⎣⎢⎢⎡xg^×t^yg^×t^zg^×t^0xtytzt0x−gy−gz−g00001⎦⎥⎥⎤
3. P r o j e c t i o n Projection Projection (投影变换)
投影就是将3D的图形投影到2D的平面上,即将三维物体转换成能在能在屏幕上显示的二维图像。投影主要分成正交投影和透视投影,如图所示
- 正交投影是假设Camera位于无限远的位置,投影出来的物体不论近处还是远处,大小都是一样大,适用于工程制图。
- 透视投影进大远小,更符合人眼的观察效果;
3.1. O r t h o g r a p h i c Orthographic Orthographic p r o j e c t i o n projection projection(正交投影)
粗暴做法1.0
正交投影是把相机固定在原点上,
l
o
o
k
−
a
t
look-at
look−at方向为
−
z
-z
−z轴,
u
p
up
up方向为
y
y
y轴,如果要对物体进行正交投影,只需要将三维坐标中的z坐标直接丢弃,就能够得到投影的结果,如图所示,投影平面为
z
=
0
z = 0
z=0,直接丢弃
z
z
z坐标或者直接令
z
z
z坐标为
0
0
0,就可以得到投影的效果。
常规操作2.0
在坐标系统,使用六个数即可定义个立方体
如
x
=
1
如x=1
如x=1代表一个面,
x
=
−
1
x=-1
x=−1代表一个面,六个数定义6个面,包围起来的立体就是立方体,用
l
(
l
e
f
t
)
l(left)
l(left),
r
(
r
i
g
h
i
t
)
r(righit)
r(righit) ,
b
(
b
o
t
t
o
m
)
b(bottom)
b(bottom) ,
t
(
t
o
p
)
t(top)
t(top) ,
f
(
f
a
r
)
f(far)
f(far) ,
n
(
n
e
a
r
)
n(near)
n(near)六个数定义一个立方体.
最右边的立方体先经过平移,缩放,最终投影的立方体在[-1,1]之间。正交投影矩阵表示为
M
ortho
=
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
n
−
f
0
0
0
0
1
]
[
1
0
0
−
r
+
l
2
0
1
0
−
t
+
b
2
0
0
1
−
n
+
f
2
0
0
0
1
]
M_{\text {ortho }}=\left[\begin{array}{cccc}\frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1\end{array}\right]\left[\begin{array}{cccc}1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1\end{array}\right]
Mortho =⎣⎢⎢⎡r−l20000t−b20000n−f200001⎦⎥⎥⎤⎣⎢⎢⎡100001000010−2r+l−2t+b−2n+f1⎦⎥⎥⎤
3.2. P e r s p e c t i v e Perspective Perspective p r o j e c t i o n projection projection(透视投影)
在学习透视投影之前,要先了解一些知识:
(
x
,
y
,
z
,
1
)
(x,y,z,1)
(x,y,z,1),
(
k
x
,
k
y
,
k
z
,
k
!
=
0
)
(kx,ky,kz,k!=0)
(kx,ky,kz,k!=0),
(
x
z
,
y
z
,
z
2
,
z
!
=
0
)
(xz,yz,z^2,z!=0)
(xz,yz,z2,z!=0),全都代表了同一个
(
x
,
y
,
z
)
(x,y,z)
(x,y,z)点。齐次坐标
(
x
,
y
,
z
,
w
)
(x,y,z,w)
(x,y,z,w)所代表的点为
(
x
/
w
,
y
/
w
,
z
/
w
)
(x/w , y/w , z/w)
(x/w,y/w,z/w)。
要进行透视投影的话,需要完成两步
1.
M
persp
→
ortho
M_{\text {persp } \rightarrow \text { ortho }}
Mpersp → ortho
2.
M
persp
=
M
ortho
M
persp
→
ortho
M_{\text {persp }}=M_{\text {ortho }} M_{\text {persp } \rightarrow \text { ortho }}
Mpersp =Mortho Mpersp → ortho
什么意思呢?我们可以将透视投影看成两部分,首先先把透视投影的远近平面挤压,到一个平面上,然后根据正交投影的方式实现成像
综上所述,透视投影矩阵为
M
persp
=
M
ortho
M
persp
→
ortho
M_{\text {persp }}=M_{\text {ortho }} M_{\text {persp } \rightarrow \text { ortho }}
Mpersp =Mortho Mpersp → ortho =
[
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
n
−
f
0
0
0
0
1
]
[
1
0
0
−
r
+
l
2
0
1
0
−
t
+
b
2
0
0
1
−
n
+
f
2
0
0
0
1
]
\left[\begin{array}{cccc}\frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1\end{array}\right]\left[\begin{array}{cccc}1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1\end{array}\right]
⎣⎢⎢⎡r−l20000t−b20000n−f200001⎦⎥⎥⎤⎣⎢⎢⎡100001000010−2r+l−2t+b−2n+f1⎦⎥⎥⎤
(
n
0
0
0
0
n
0
0
0
0
n
+
f
−
n
×
f
0
0
1
0
)
\left(\begin{array}{cccc}n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -n \times f \\ 0 & 0 & 1 & 0\end{array}\right)
⎝⎜⎜⎛n0000n0000n+f100−n×f0⎠⎟⎟⎞
在MVP之后应该做什么?
回顾一下MVP:
1. m o d e l model model t r a n s f o r m a t i o n transformation transformation( p l a c i n g placing placing o b j e c t s ) objects) objects)
- v i e w view view t r a n s f o r m a t i o n ( p l a c i n g transformation(placing transformation(placing c a m e r a ) camera) camera)
- P r o j e c t i o n t r a n s f o r m a t i o n Projection transformation Projectiontransformation
- O r t h o g r a p h i c Orthographic Orthographic p r o j e c t i o n ( c u b o i d projection(cuboid projection(cuboid t o to to “ c a n o n i c a l ” “canonical” “canonical” c u b e [ − 1 , 1 ] 3 ) cube [-1,1]^3) cube[−1,1]3)(长方体转换到规范立方体当中)
-
P
e
r
s
p
e
c
t
i
v
e
Perspective
Perspective
p
r
o
j
e
c
t
i
o
n
(
f
r
u
s
t
u
m
projection(frustum
projection(frustum
t
o
to
to
“
c
a
n
o
n
i
c
a
l
”
“canonical”
“canonical”
c
u
b
e
)
cube)
cube)(平截头体转换为规范立方体)
在最后投影变换结束后,我们所需要的图像被投影到了规范立方体中,那么应该对规范立方体进行怎样的处理?
将规范立方体的投影显示到屏幕上(Screen)
在转化时有两点要注意: - 与 z z z无关( z z z的值其实是物体在世界空间中的深度值,但是目前我们只有一个物体,所以不考虑他)
- 对 x o y xoy xoy平面进行转换, [ − 1 , 1 ] 2 [-1,1]^2 [−1,1]2转换到 [ 0 , w i d t h ] × [ 0 , h e i g h t ] [0,width] × [0,height] [0,width]×[0,height]
M viewport = ( w i d t h 2 0 0 width 2 0 height 2 0 height 2 0 0 1 0 0 0 0 1 ) M_{\text {viewport }}=\left(\begin{array}{cccc}\frac{w i d t h}{2} & 0 & 0 & \frac{\text { width }}{2} \\ 0 & \frac{\text { height }}{2} & 0 & \frac{\text { height }}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\end{array}\right) Mviewport =⎝⎜⎜⎛2width00002 height 0000102 width 2 height 01⎠⎟⎟⎞
称这个矩阵为视口矩阵。
这个矩阵的具体实现首先对物体进行位移,因为规范立方体中的中心位于原点的位置,而屏幕空间的坐标是从左下角开始为原点
(
0
,
0
)
(0,0)
(0,0),不存在负坐标,所以先将规范立方体的中心移动到
(
w
i
d
t
h
/
2
,
h
e
i
g
h
t
/
2
)
(width/2,height/2)
(width/2,height/2)的位置,然后再对规范立方体进行拉伸,拉伸比例如矩阵所示。因为与
z
z
z无关,所以对
z
z
z不做任何变换。