入门图形学5——变换2
5.1 变换的组合
5.1.1 任何变换都可以由单个变换组合得到
- 在上一节我们了解到了基本的变换类型了,并接触了将变换统一的坐标类型——其次坐标,还了解了其表现形式,其次矩阵。
- 这一节我们来看变换组合中需要注意的点。
- 事实上,任何变换都可以由单个变换组合而来,但他们的顺序却是需要考虑的。
5.1.2 不同的顺序带来不同的结果
5.1.2 不同的变换顺序带来的结果不同
- 图中是一个变换的例子,它先进行了平移而后进行了旋转,但如果是先旋转再平移,呈现出的结果就不同,这很好理解,因为操作导致顶点位置发生了改变,因此就会使得结果不一样。
- 这也表明了数学上,矩阵不符合交换律。因此往往平移是最后发生的。
- 我们往往应用矩阵的顺序是由右向左进行的。
5.1.2.1 矩阵的应用是由右向左进行的
- 但矩阵同样具有结合律,因此我们可以将复杂的矩阵操作何为一个矩阵来对向量进行操作变换,例如MVP矩阵。
5.1.3 变换的分解
- 变换能够组合自然也能够分解,一些复杂的变换我们都可以通过将其分解为简单变换来实现,比如下面这个变换。
5.1.3 变换的分解
- 仔细观察这个变换,实际上它做的操作是将该图形平移到远点后,对其旋转,而后再平移回这个图形位置,这样就用我们已有的知识完成了一个复杂的不以原点为中心旋转的变换。在后续的学习过程中我们都应该保持这种思考方式,化繁为简,抓住主要矛盾。
5.2 三维的变换
5.2.1 知识的迁移
- 实际上,三维空间中的坐标变换与二维空间类似,本质上只不过多了个维度,我们依然使用其次坐标方式表示任何变换。
5.2.1 一个三维变换矩阵
- 这里闫老师在101中给大家提了一个小思考,三维空间中是先考虑线性变换还是先考虑平移呢?
- 相信大家已经有了自己的答案,当然是先考虑线性变换啊!多加了个维度本质都是通用的嘛!
5.2.2 三维空间的旋转
- 三维空间中的旋转可能乍一看很复杂,但我们同样可以对其进行分解。
- 以下是分别按X,Y,Z轴向进行旋转的旋转矩阵,请各位观察其特点。
5.2.2 三维轴向旋转矩阵
- 很容易可以发现,绕哪个轴旋转哪个轴的列不变,为1,这里涉及到之前提到过矩阵乘法,希望大家自己动手试一试,看看是不是这样。
- 细心的同学会发现了,有点小问题,为何中间的旋转矩阵右上方的sina 符号不太对?这是因为叉乘的性质,实际上,如果我们要得到一个现在图中的正方向的y我们需要用x叉乘z,这与其他两个方向正好相反(回顾左右手定则!)因此我们需要颠倒他们的符号。
5.2.3 一般的三维旋转
- 我们会介绍三大方法,分别是欧拉角,矩阵法,四元数法,它们各有利弊。
- 1.欧拉角
- 我们分别定义绕三个方向的旋转为ROll,Yaw,Pitch,这三个旋转方式,它们的任意组合就可以成为一个任意的旋转角度。
5.2.3 欧拉角旋转
- Rxyz(a,β,γ) = Rx(α)Ry(β)Rz(γ)
- 但不可避免的会有一些问题,比如万向死锁,你可以浏览这个视频来了解
- 2.矩阵法任意轴旋转:罗德里德斯公式
5.2.3.1 罗德里德斯公式
- 将该向量平移到原点后再变换
- 感兴趣的同学可以自行推导这个公式是如何产生的。这里放一下闫老师推导的过程。
5.2.3.2 罗德里德斯公式的推导
- 依然有缺点,那就是矩阵蠕变,简单来说就是矩阵运算参数出现差错导致整个矩阵出现问题
- 3.四元数
- 是一种便于做旋转差值的方法,抽象出第四位度的虚数轴。
- 这里不会详细展开,有兴趣的可以查看这个视频来了解
5.3 视图变换和投影变换
5.3.1 类比拍照的MVP变换
- 在生活中,我们经常需要拍摄某些事物,可能是美丽的风景,也可能是人物,动物等等,拍摄的过程大致可以分为三步:
- 将物体摆好位置——模型变换
- 调整好适合的角度——视图变换
- 将三维场景拍摄到二维照片中——投影变换
- 以上就是图形学中最重要的将三维场景投射到二维画面中的操作——MVP矩阵。
5.3.2 视图变换
- 第一步,定义相机,如果我们要定义一个摄像机,最基本的要素是什么?没错,是摄像机的位置,这就是第一个要素Position,随后我们要拍摄物体,那么我们要定义相机向何处看,这是第二个关键点,Look——at观看的视角方向,第三个关键点,我们如何规定相机的旋转呢?我们需要固定一个向上的方向来确定相机视图的旋转。
- 因此我们得出了相机的三要素——POSITION,LOOK_AT,以及UP
- 第二部,我们来思考如果要得到一张图像,我们具备了摄像机的这三个属性,如何让摄像机移动的同时物体也进行移动呢,最好的选择就是,将摄像机放在原点位置,我们还为其规定了上一步提到的两个属性:LOOK_AT和UP,分别是-Z以及Y,你会发现他们也是满足叉乘结果的。
5.3.2 摄像机的位置与方向
- 如何将任意一点的摄像机移动到标准的观察位置呢?这就需要应用我们之前学到的矩阵了,我们需要先将摄像机移动到原点位置,再将视角方向和向上方向旋转到-z与y上。
- 这需要我们进行矩阵变换,之前在三维变换中我们已经了解过,矩阵的三维变换需要先平移后做其他的线性变换,那么看起来应该是这样的:
5.3.2.1 视图变换矩阵
- 平移变换很好写,我们只需要让任意一个点乘以一个平移值为(-x,-y,-z)的其次平移阵就好了,看起来就像这样:
5.3.2.2 视图变换中的平移变换
- 但接下来就不太好写了,我们如何将任意方向的轴旋转到固定的方向呢?这其实就要用到我们本节提到的新知识了,旋转矩阵是一个正交阵,如果你忘了正交阵是什么,回到第3讲中查看一下吧,我们继续,正交阵的特点是其转置等于逆,逆阵又是啥,逆阵相当于是反向的操作,也就是说我们只需要先整出来一个将确定方向的向量旋转到任意方向的矩阵就好了,这很好做,随后我们只需要将其转置,就可以得到我们需要的矩阵了:
5.3.2.3 正交矩阵的逆等于其转置
- 这样我们就完成了视图变换
5.3.3投影变换
- 投影变换分为两种:
- 1.透视投影
- 2.正交投影
- 两者的共同点都是将三维的视图投影到二维画面上的过程,两者之不同是在于后者正交投影没有所谓的透视效果,也就是近大远小的效果,我们分别来看,首先是正交投影
5.3.3 投影变换
- 正交投影
- 正交投影模拟的是在摄像机距离物体无限远时,物体投射到摄像机屏幕上的效果,因为距离很远,因此就没有透视效果,可以看上图右图上的结果。
- 正交投影的操作是什么呢?实际上它是规定了空间中任意一个立方体的上下左右前后这三组平面,分别为TB,LR,以及NF(也被成为近,远裁剪平面),其中NF不太好理解,因为我们是以右手坐标系为标准,因此实际上数值来讲F比N更小。(OpenGl中是左手坐标系)其F比N更大。
- 之后正交投影将其分别映射到位于原点的正则标准正方形(1^3)上,这就完成了正交投影的变换。
- 我们来看矩阵实现,很简单,我们需要做的事情是,首先,将这个立方体移动到原点位置,用的是一个平移矩阵,之后,我们将这个立方体缩放至标准大小也就是xy∈【-1,1】区间内。
5.3.3.1 正交投影变换矩阵
- 我们来看一下Unity里的正交投影和透视投影,正常移动摄像机对应的是透视投影,但当我们点到视口栏中的2D选项实际上就是正交投影。
5.3.3.2 Unity中的正交投影
- 透视投影变换
- 透视投影实际上与正交投影最大的区别就是,两条平行线在屏幕上看起来会变成相交的了,这其实比较容易理解,就像我们看火车轨道,街道尽头,我们都能指出它们相交的地方,也就是交点,这就是透视效应。
- 那么我们该如何理解透视投影呢?实际上做了些什么呢?我们可以这样理解,虽然与正交投影不同,透视投影远近平面是不一样大的,但我们可以在保证他们的远近比例关系情况下,将透视投影视椎体“挤压”成为一个正交投影的长方体视椎体,最后就可以用我们已经学会的正交投影来对其进行处理了。
5.3.3.3 如何做透视投影?
- 通过我们初中学习的相似三角形知识,我们可以对这个过程进行一个分析,我们专注于y值,那么我们会发现如果要将f平面上方的点挤压到与n平面平行的点,我们就要考虑如下视图中相似三角形的关系:
5.3.3.4 NF平面的透视三角形关系
- 我们可以得到以下比例关系式:N/Z = Y’/Y ,因此就可以推出Y’ = N/Z * Y
- x的推理过程一模一样,不再赘述,最后得到X’ = N/Z * X
- 目前我们知道了XY变化的过程,对于Z任然不知道,但没关系,我们已经可以根据其它关系推导出完整的矩阵了,还记得之前我们怎么推导二维旋转矩阵的吗?欢迎各位跟我一起推导,下面放出我的手写推导过程
- 手推过程较长,各位只要细心观察一定能最后得到一样的结果。
5.3.3.5 MVP——透视投影矩阵推导过程
- 这样,经过这一个矩阵变换我们就可以得到位于裁剪空间下的物体坐标了。
5.3.4 裁剪空间与裁剪平面
- 前文我们提到过了裁剪平面这个概念,裁剪平面实际上就是摄像机能看到的空间范围,一共分为6个裁剪平面。在Unity中,我们可以通过调节Near与Far裁剪平面与摄像机视口的距离,来决定裁剪空间的大小。
5.3.4 unity中的摄像机组件
- 我们之前的工作,实际上就是将场景中的物体,通过一系列缩放,平移变换,映射到这个裁剪空间之中,何为裁剪?相信之前认真观察的同学能够留意到我们的第四维变量W,该变量实际上就是一个判断区间的范围。
- 如果物体顶点在这个裁剪范围,则会被保留,而若在这个裁剪范围外,则将会被剔除。我们来看一下详细的过程
- 首先,不同空间对应的裁剪坐标范围不同,Unity使用的OPenGL裁剪空间的范围是【-z,z]。如果超出这个范围则将被剔除,这事就会有疑问,如何剔除呢?
- 我们会将物体分为几种类型,完全在裁剪空间内的,一半在裁剪空间内的,以及完全在裁剪空间外的。
- 接着我们会对其进行裁剪,对于一半处在裁剪空间内的边缘情况,我们将进行进一步的操作,划分三角形,对于三角形,我们根据其每个顶点与平面的位置关系来判断是否要裁剪它,若需要裁剪,则我们将边界作为一条新的边,与在边界内的三角形部分形成一个新的几何体。
5.3.4.1 裁切三角形
5.3.5 其次除法与视口坐标映射
- 在完成上述的MVP变换后,我们就需要将图像呈现在屏幕上,在此之前,为了方便计算,我们会将XYZ三个量全部除以W,将其归一化到归一设备坐标(NDC)下。这样便于计算,接着,我们将单独提取这个立方体内的物体的x,y坐标,并将其变化到屏幕上,这个过程被称为视口坐标映射,同样也是利用矩阵操作完成的。我们对物体映射在屏幕上的像素坐标位置,是这么计算的:
5.3.5 其次除法与视口坐标映射
- 至此,我们就可以得到物体在屏幕像素上的位置了。不过就像我们在一开始所说的那样,这个映射方式在不同的API中定义并不相同,OPenGL直中与DX中是相反的,需要我们留意。
参考资料
- games101图形学入门——闫令琪 https://www.bilibili.com/video/BV1X7411F744
- 游戏开发入门——数学和物理 徐芝琦等著
- Fundamental Of ComputerGraphics(虎书)by Steve Marschner
- 计算机图形学入门——3D渲染指南 GabrielGambetta著 贾凡译
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Pleasant233!