1.数学基础
1.数学基础
鲸拓工作室本系列的主要目的是复盘并总结计算机图形学这个学科常用算法与原理,会从基本的数学理论讲起,同时会附带部分算法的代码实现,由浅入深,只需初中的数学基础就行。主要参考了GAMES101-现代计算机图形学入门这门课(具体引用见文章末尾),同时附加上自己的理解。有兴趣的也可直接看视频。
基础铺垫
计算机视觉可大致分为光栅化(Rasterization)、曲线和网格(Curves and Meshes)、光追(Ray Tracing)、动画(Animation / Simulation)这四个方面。其中会着重介绍前3个方面,在此之前,让我们先来了解一些数学知识吧(非常重要,建议不要跳过)
向量
向量的计算公式如下:
向量的长度可以这样表示
向量的加法
平行四边形法则、三角形法则
向量的减法可以复用这两个法则,如a - b = a + (-b)
向量的乘法
向量的乘法分为点乘和叉乘
点乘
点乘的结果是点积,即乘出来的结果是一个数,表示
同时点乘满足交换律和分配律,有如下性质
叉乘
叉乘又称向量积,其运算结果是一个向量,并且与这两个向量都垂直,是这两个向量所在平面的法线向量。使用右手定则确定其方向(右手握拳,四指从A旋转至B,最后大拇指所在方向就是法线方向)。
叉乘的性质如下(不满足交换律)
详细计算方法如下
可以用叉乘来判断一个点是否在三角形内部
根据右手定则可知:AB叉乘AP的结果向外,AB叉乘AC的结果向外,说明点P和点C在AB的同侧;
BC叉乘BP的结果向外,BC叉乘BA的结果向外,说明点P和点A在BC的同侧;
CA叉乘CP的结果向外,CA叉乘CB的结果向外,说明点P和点B在AC的同侧;
综上可知,P在三角形ABC的内部。
若发现点P与任意一个点不在一条边的同侧,则说明该点在三角形外。
正交
两个向量正交,就说明两两垂直
矩阵
一个M*N的矩阵就是M行,N列的数
矩阵乘矩阵还是一个矩阵:(M x N) (N x P) = (M x P)
注意,A的列数必须与B的行数相等才能做矩阵乘法,否则不能乘。
矩阵的性质
矩阵满足分配律和结合律,不满足交换律
矩阵的转置
逆矩阵
向量的点乘和叉乘都可以用矩阵的形式表示
变换
线性变换
缩放
翻转
切变
旋转
这里可以多扩展一下,如果我们旋转 -θ,会得到一个怎样的矩阵呢?
总结:线性变换的方程如下:
齐次坐标
除了上述变换外,还有平移需要考虑。平移的方程如下
观察这个方程,我们可以看出来,它除了变量x、y之外,还有两个常量。像这种形式的方程,我们没有办法写成矩阵的形式。但很显然,我们并不想有这么个特殊的个例,为了将它写成矩阵的形式,我们可以将它的维度上升,变成三维,即齐次坐标。具体定义如下:
注:由于向量具有不变性,所以用0表示向量可以保护其在经过一系列变换之后仍能维持不变。
这样表示之后,我们便可以将平移方程转换成矩阵的形式
我们可以验证这样定义之后,对点和向量之间的运算是否会有影响:
- 向量 + 向量 = 向量 (0 + 0 = 0 )
- 点 - 点 = 向量 (1 - 1 = 0)
- 点 + 向量 = 点 (1 + 0 = 1)
那么点 + 点等于什么呢?这里需要补充一下,在齐次坐标系中,有如下变换规则
所以,点 + 点 = 中点
仿射变换
仿射变换是一个向量空间变换到另一个向量空间的过程。下图指从普通二维向量升维到三维齐次坐标的变换过程
那么,对上面的二维变换,我们同样可以用齐次坐标的方法来表示
逆变换
逆变换是指将变换复原的过程,很简单,只需要乘上变换矩阵的逆矩阵即可
组合变换
上述几种简单的变换可以组合在一起,形成比较复杂的变换。但是要注意,矩阵不满足交换律,所以变换过程的顺序很重要,同样的变换操作,如果顺序不对,就会得到不同的结果。
当我们定义好变换操作和顺序之后,我们应该将变换矩阵从右往左写(左乘)
复杂变换
对于一些比较复杂的变换,比如要求围绕模型的某一个顶点(不在原点)做旋转操作。我们可以将其平移到原点,旋转完之后再平移回去。这一点在后续的3D场景中被广泛运用。
3D变换
3D世界中的变换与2D的类似,依旧是升维成齐次坐标系再做矩阵运算
视图变换
我们可以通过这三个数,定义任意一个角度的旋转,这也叫做欧拉角
投影变换
摆正摄像头
现在,我们已经知道了模型的旋转和各种移动操作,那么,我们应该怎样把这些结果展示到摄像机面前呢?要搞清楚这个问题,我们需要先定义一个摄像机。这里我们可以认为,假如一个摄像机的位置确定了,它的朝向确定了,并且向上方向也确定了,那么就可以说这个相机就定义好了(这里可以记一下下图中的几个符号,为了方便,后文主要用这几个符号来表示对应的方向)
在渲染的过程中,我们通常让相机保持不动,让物体运动。为了方便计算,我们通常把相机定在原点,让它往 -Z 轴看,向上方向沿着 Y 轴。这个过程用数学描述出来,需要有如下几个步骤:
- 将相机移动到原点
- 将 g 旋转到 -Z 轴
- 将 t 旋转到 Y 轴
- 将 g × t(叉乘代表这两个向量的法线方向) 旋转到 X 轴
很明显,这个过程很难写!
我们将这个视图变换矩阵定义为
移动矩阵的写法很容易
难的是旋转矩阵。我们可以思考,将这三个方向都旋转到指定的轴,那么反过来想,就是要把 X 轴转向 (g × t),Y 轴转向 t,Z 轴转向 -g。而这不正是旋转矩阵的逆矩阵吗
那么上面我们证明过,旋转矩阵的逆矩阵,就是他的转置,应用这个结论,我们可以知道,这个旋转矩阵应该就是上面矩阵的转置
好了,经过这个变换,我们已经能够把相机摆正到原点上了。那么接下来,就要开始把物体投影到相机上。目前投影操作分为正交投影和透视投影,先通过下图来直观的了解下两种投影方式,我们一个个来介绍。
正交投影
简单的理解正交投影:就是把物体的Z轴拖到 0 的位置,然后把物体移动和缩放到
流程如下:
这个过程很直觉,但我们也需要用数学的方法表示出来,其矩阵如下所示:
透视投影
透视投影会造成近大远小的效果,也会导致本来平行的线变得不平行(参照下面的铁轨照片),但是这也是最符合人眼的投影方式
在此之前,我们先复习一下齐次坐标的性质:
透视投影的步骤也很简单,就是把一个物体压成立方体,然后再做正交投影,注意近平面n、远平面f,这两个平面在深度上保持不变(即z轴不动,留给正交投影)(只是这两个平面的Z轴不变,其内部的点可能会发生改变)
这个变化最重要的就是要找到变化前和变化后的点之间的关系,我们可以用相似三角形来帮助理解
这里的n是投影之后的Z值,z是原本的Z值。通过相似三角形的性质,我们可以得出x和y的变化关系如下
这里补充一下我的个人理解:因为相机是朝向 -Z 轴的,在缩放的过程中,Z轴的数值是在不断变化的,但x,y的变化可以根据z的变化而确定,所以这里就可以用上述公式表达出他们之间的关系。但是Z我们怎么求呢,且看下面的分析。
我们先把这两个公式用齐次坐标的方法表达出来,得到下面的矩阵
提取出变化矩阵,可以得到下面的表达(如果不清楚的话,可以自己乘起来验证一下)
那么这个矩阵还剩下4个未知数,而我们还有两个如下性质没有使用:
- 近平面上的每一个点都不变
- 远平面上每一个点的Z轴的值都不变
首先运用第一个性质,我们可以得到下面的变化
由此可以解出两个未知数,并得到下面的公式
接着用第二个性质,可以写出如下变换,并得到下面的公式
由此组成的公式组就可以算出剩下的两个未知数了
至此,这个压缩过程的矩阵就全部表示出来了
视口变换
经历了上面几次变换,我们能得到一个