MVP变换
计算机图形学其实就是一种利用数学算法,将二维或三维的场景转化成,计算机显示器能够显示的栅格图像的科学。
在三维场景中,模型渲染成一个二维的画面经过了一系列复杂的数学运算。
MVP变换就是这些数学运算中比较重要的一种。
MVP变换其实对应了三种变换:
- 模型变换(Model Transfromation)
- 视图变换(View Transformation)
- 投影变换(Projection Transformation)
这三种变换可以形象的理解成如何拍一张好看的照片。
如何拍摄一张好看的照片
摆好pose
找一个好的地方,所有模特都集合到哪里,摆好pose。
这一步在图形学里面对应模型变换(Model Transfromation)。
摆好相机
找一个好的位置架设相机,让相机朝着某一个角度去看。
这一步在图形学里面对应视图变换(Viewe Transformation)。
茄子
把相机看到的场景投影到一张相片上。
这一步在图形学中对应投影变换(Projection Transformation)。
模型变换
模型变换其实就是各个模型进行各自矩阵变换的过程,具体可以看图形学基础—矩阵
视图变换
视图变换就是摆摄像机,确定一个相机的摆放需要定义三个参数:
- 相机的位置(position)
- 相机看向的方向(gaze direction)
- 相机的上方向(up direction)
如何进行视图变换

两个物体如果做相同的运动,那么可以看作这两个物体之间仍然保持静止。
也就是说当相机和场景中的所有物体都执行相同的运动时,拍出来的结果不会发生任何变化。

既然这样的话,我们就可以将相机永远放在一个标准的位置(相机位置永远在坐标原点,相机永远向-Z方向看,相机永远以Y轴作为向上方向)。
为了使相机与场景保持相对静止,就需要相机和场景中所有物体都执行相同的操作,也就是乘以相同的变换矩阵。
这个变换矩阵就是我们说的视图变换矩阵。
视图变换矩阵的作用可以理解成,将场景中的相机变换到标准位置,为了使场景与相机保持静止,那么场景中的所有物体都需要乘上该矩阵。
如何计算
直接计算将场景中的相机变换到标准位置是非常困难的。
但是有一件事情很简单,就是将一个标准位置下的相机,变换到当前相机的位置,我们假设这个变换过程为V。
那么将当前相机位置变换回标准位置,其实就是做一次V变换的逆变换而已,也就是求V的逆矩阵V−1。
那么此时这个矩阵V−1就是我们需要计算的视图变换矩阵。
这个变换矩阵可以分成三个部分:平移、旋转、缩放
平移:
将标准相机放置到当前相机位置的矩阵可以表示成100001000010txtytz1
这个变换的逆变换就是直接将平移量乘上-1即可100001000010−tx−ty−tz1
旋转:

将标准相机旋转到与当前相机的方向一致的矩阵,可以通过将 X旋转到e(g x t)、Y轴旋转到t、Z轴旋转到-g 这三个矩阵相乘得到。
最终将标准相机旋转到与当前相机的方向一致旋转矩阵可以表示成Xg^×t^Yg^×t^Zg^×t^0XtYtZt0X−gY−gZ−g00001
而旋转矩阵是正交矩阵,也就是说旋转矩阵的逆矩阵就等于它的转置矩阵,因此计算该矩阵的逆矩阵只需要对上面的旋转矩阵部分转置即可。
最终将当前相机的方向旋转到与标准相机方向一致旋转矩阵可以表示成Xg^×t^XtX−g0Yg^×t^YtY−g0Zg^×t^ZtZ−g00001
缩放:
缩放矩阵表示成sx0000sy0000sz00001
缩放矩阵的逆矩阵为1/sx00001/sy00001/sz00001
最终的视图变换矩阵
将上面计算得到的三个逆矩阵相乘在一起,最终得到的矩阵就是我们需要的视图变换矩阵
100001000010−tx−ty−tz1Xg^×t^XtX−g0Yg^×t^YtY−g0Zg^×t^ZtZ−g000011/sx00001/sy00001/sz00001
投影变换
投影变换有两种:正交投影和透视投影,分别对应两种相机:正交投影相机,透视投影相机。


经过正交投影得到的画面中,平行线仍然是平行的,不会有近大远小的效果,大多用于工程制图。
经过透视投影得到的画面中,平行线不再平行,有近大远小的效果,人眼的成像类似于透视投影。
正交投影

由于前面通过视图变换已经将相机摆放在了标准位置,因此,正交投影只需要将Z方向压平,最后再将X和Y的范围映射到-1到1即可。
计算

首先定义一个空间中的立方体,具有上平面t,下平面b,左平面l,右平面r,近平面n,远平面f。
然后将这个空间中的立方体平移到标准位置。
再将这个立方体缩放成为一个标准立方体(长宽高范围都为-1到1)。
将上面的三个步骤表示成矩阵形式就是:r−l20000t−b20000n−f200001100001000010−2r+l−2t+b−2n+f1
最终得到的矩阵就是正交投影矩阵。
透视投影

通过对比透视投影的正交投影可以发现,透视投影和正交投影其实类似,只不过透视投影的远平面比近平面要大,而正交投影的远平面的近平面大小一样。
那么通过观察可以发现,如果将透视投影的远平面进行挤压,最终压成和近平面一样大,那就得到了一个正交投影。
而透视投影矩阵也正是这么计算的。
计算
计算透视投影可以分成两步:首先将透视投影的视锥挤成正交投影的视锥,然后再进行一次正交投影。
而计算正交投影已经写出来了,那么目前唯一的问题就是,怎么将透视投影的视锥挤成正交投影的视锥。
在挤压之前,首先规定:
- 近平面上的任何一个点在挤压的过程中永远不变
- 远平面上的任何一个点在挤压的过程中Z值不会发生变化
- 远平面的中心点在挤压后仍然是中心点

从侧面看透视投影视锥的上半部分可以表示成上图的形式。
通过相似三角形可以得到,近平面上的点 (x′,y′,z′) 和视锥任意平面上的点 (x,y,z) 他们的Y坐标满足 y′=zny
同理X坐标的对应关系也满足 x′=znx
因此可以的到x′y′z′1=znxznyunknown1
由于齐次坐标定义了xyzw=x/wy/wz/w1
所以x′y′z′1=znxznyunknown1=nxnyunknownz
表示成矩阵的形式就是x′y′z′1=nxnyunknownz=n0?00n?000?100?0xyz1
可以看到目前的信息中,矩阵的第三行元素还不知道是什么,那么现在就只需要计算第三行的元素即可。
而矩阵的第三行与Z值相关,同时我们又定义了在挤压的过程中:
1、近平面上的点不变:
n0?00n?000?100?0xyn1=xyn1=nxnyn2n
所以单看矩阵的第三行可以得到(0,0,A,B)xyn1=n2
2、远平面上的点Z值不变,并且中心点还是中心点:
n0?00n?000?100?000f1=00f1=00f2f
所以单看矩阵的第三行可以得到(0,0,A,B)00f1=f2
联立上面两个观察可以得到{An+B=n2Af+B=f2
最后解方程组可以得到{A=n+fB=−nf
因此矩阵就可以完整的写出n0000n0000n+f100−nf0
该矩阵将透视投影的视锥挤压成了正交投影视锥,因此要完成最终的投影,只需要再进行一次正交投影即可。
假设透视投影矩阵记做Mpersp,正交投影矩阵记做Mortho,刚刚计算的透视转正交矩阵记做Mpersp→ortho。
那么就有Mpersp=MorthoMpersp→ortho
完整的MVP变换
场景中的每一个模型,都会执行一次MVP变换,使得模型最终以正确的方式呈现在屏幕上。
首先模型乘以自身的模型矩阵,将标准位置下定义的模型放置到世界坐标当中。
然后乘以视图矩阵,将模型变换到了相机坐标系下
最后乘以投影矩阵,将相机坐标系下的模型投影到一个-1到1的经典立方体当中。
在模型经过MVP变换之后,通常还需要做一次视口变换,将-1到1的范围映射到屏幕空间中。