101:02-04
图形学所需要的一些基础学科(然而之前我不懂它们的重要都没好好学,泪目):
高数,线代,概率论基础物理(光学、力学)信号处理!!!!
罢了,好在也不是完全没学,起码打下了基础。

其实这部分内容,之前数字媒体数学基础的时候已经学了挺多。上学期图形学又复习了一遍,所以关于如何利用矩阵对向量进行平移旋转和缩放。我就不赘述了。
记录一下之前没太特意记的吧。和之前自己一些潜意识应用的总结。
向量点乘:其实从数学上还有个快速算法,就是b在a上的投影的长度乘以a的长度。我对于点乘的概念,经常解释为判断两个向量的重合程度。图形学官方则是用夹角来说明,不过夹角也确实更准确。首先b垂直a的时候,点乘是0,然后偏向于a那边点乘就是正,远离就是负。按我的话来说,如果两个都是单位向量,它们越重合,点乘就越接近1,越相反,点乘越接近-1。

点乘的坐标运算,这个真的快忘记了,这里就复习一下吧。其实也挺好记。

点乘在图形学里最大作用就是找夹角。还有计算投影长,来把向量正交分解。比如我们已经学的一些光照模型。
叉乘:两个向量叉乘的结果是垂直于这两个向量的新向量。并且遵循右手定则来决定方向。(如右图,拇指伸直右手四指从a方向转向b方向,拇指方向为结果方向)长度计算则如图。

这个可以用来定义坐标系。(比如之前的切线空间就是确定了法线和切线方向后,叉乘得出副切线方向)然后对于一个坐标系的三个轴,如果xy叉乘得到z,那么它就是右手坐标系,得-z则为左手。向量叉乘它自身结果为0。关于叉乘的快速用法,我这里介绍一下多年前高中时候从坤哥那里看来的方法。口诀:主减副,副减主,主减副。用法如右图。

叉乘主要用途,用来判断两个向量的左右或者前后关系。 如右图左,在一个右手坐标系中,怎么判断a和b的左右关系呢。就是看它们的叉乘结果是正还是负。其中,左指的是逆时针方向,右指的是顺时针方向。也就是说y正半轴在x正半轴的左边。然后以图中ab为例,a叉乘b,结果指向屏幕外,说明b在a的左边。(也许你会说这不是一眼看出来吗,但是你看到的只是一个平面上的映射,它们在空间中的关系你是不清楚的。)(好吧好像不是我前面解释的角度,而是说,就算你一眼能看出来,但是计算机没眼睛啊,它看不出来,只能通过数学方式推,图右同理)(为什么结果指向屏幕外就说b在a的左边呢,你自己拿右手比划一下,是不是逆时针转就是指向外面的)
而对于图下,如何判断p点是否在三角形ABC内呢?按顶点顺序,比如ABC,首先AB叉乘AP ,可以判断P是在AB左边,然后BC叉乘BP……以此类推,发现P点都在三个边的左边,那么它就在三角形内部。(但是如果你不按abc顺序来也没关系,只要判断这个点都在三条边的同一边,那么它就在内部)
这个功能通常在光栅化里大量应用,用来判断像素是否在三角形内部。如果点在边上,那么俗语称(corner case),你自己做决定。

矩阵乘法:这里讲了一个以前从没想过的计算角度。我直呼喵啊。其实就是你知道结果是M行P列的那么你算结果的第x行y列的值的时候,就去找原来第一个矩阵的x行和第二个矩阵的y列来乘积求和。关于矩阵变换,我之前数字媒体数学基础课研究了一些结论。我这里截图一部分吧。后面想再了解可以去翻我的作业。


唉,现在学的都是大二上的数字媒体数学基础的东西,然而我现在好多都记不清了,感觉像重新学一样。不过算了,学过总是有意义的。正好这次捡起来,做一个总结,以后再忘了来这里复习。
缩放,旋转变换都可以用基变换来解释,向量乘以缩放,旋转后的基(矩阵形式),就变成了变换后的向量。这种可以用一个矩阵表示的变换也叫线性变换。平移比较特殊,它无法用基的变换来表示,所以它不是线性变换。

为了用一个矩阵表示平移,我们引入齐次坐标(homogeneous coordinates)。齐次坐标中,点的w为1,向量的w为0。这样设计有一个很妙的地方,保证了运算的正确。即向量加向量等于向量,点减点等于向量等等。这里点加点的结果是两个点的中点。为什么是这样,这要说到齐次坐标的特性。齐次坐标中同一个点的坐标有多种写法,但只要w归一后坐标一样,那它们就是同一个点。(我们可以想象在一个透视的空间中,虽然两个点离你远近不同,但是只要它们在你眼里重合了,那就是同一个点)关于齐次坐标还有很多比较奇特的定理,比如点线面关系等等,在数字媒体数学基础的课件里面都有,我就不一一总结了,用到再去看吧。



总之,当引入齐次坐标后,前面的平移问题就有了解决方法。而这种变换也叫做仿射变换(Affine Transformations)

我深入思考了半天,尝试从基变换的角度来理解为什么这个仿射变换可以造成平移的结果,下面给出我的结论。首先想象一个坐标系以及空间中的网格,而平移变换表示w基在w=1这个平面上移动了。这导致整个坐标系空间产生了形变。(我不会做动画所以难以表示我想象的画面,我尝试用右图来解释。)


也就是说这种位移是通过整个空间的变化来形成的投影上的位移(实际上,这个点在这个坐标系内的坐标没有任何改变)(可能你会说那坐标都变了怎么说没有改变,因为我们用的坐标是直角坐标系的基表示,而不是这个坐标系的基表示)感觉还是有些抽象,以后我能想到更具象的解释方法再补充吧。反正目前的我是理解了。
矩阵变换的顺序十分重要。可以看右图。

三维空间的矩阵变换,其实就是二维的拓展,没什么好说的。
好吧关于旋转还是可以说一下的。首先是基本的旋转矩阵。我们知道旋转可以通过一个轴和一个角度来表示的。

所以有一个公式,罗德里格斯旋转公式,来通过一个轴和角度来表示旋转。(这个轴默认是过原点的)其实之前关于unity的旋转,我还做了一些研究。比如万向锁和四元数的。四元数的作用其实主要是用于插值,如果我们直接通过欧拉角插值,结果往往不是正确的。不过我也忘了当时怎么研究的了。有需要去翻我那时的笔记吧。


下面讲观测变换(Viewing transformation),其下又可分为视图变换和投影变换。


首先说一下MVP变换,指的是模型(Modle),视图(View),投影(Projection)变换。其中,MV主要是把模型和摄像机的坐标从世界空间,变换到观察空间(VS,以相机为原点)中。 相机信息如何表示:需要一个点,表示位置,一个前向量和一个垂直向量,表示相机方向和顶部方向。

然后接下来就是求坐标系的变换矩阵了。这里我们再次复习一下:假如有两个基,a基和b基(矩阵形式),有一个向量v,如果我想把b基下的向量v(即vb)转换为a基下的向量v(即va)那么va等于(vb)乘(a基下的b基) 。想想之前的TBN矩阵,我们要从切线空间b转换到世界空间a,那么就要把向量乘世界空间下的切线空姐基坐标构成的矩阵。而这很容易拿到,因为切线法线这些一开始就是世界空间下的坐标了。
在这里,我们首先把相机移动到原点位置。这里我思考了半天,为什么这里要平移而TBN矩阵不用平移呢?我得出的结论是:首先,视图变换涉及到了模型顶点坐标的位置的变换,而且哪怕从基变换的角度,从旧基到新基也是一个平移旋转的过程,所以视图变换这边是完全正确的。而TBN矩阵那边,则是因为在整个过程中,只涉及了方向的变换,没涉及位置的变换,(我们知道,在空间中,方向的表示是唯一的,哪怕可视化后看起来你是从空间某一点出发的方向,但是在坐标里你都是从原点出发的。因此,TBN矩阵的基变换其实只涉及了旋转变换)所以不用平移这个步骤。
平移之后是旋转操作,回忆上面的基的变换,我要把所有坐标从世界空间转换到观察空间(或者相机空间),那么需要乘以观察空间下的世界空间的基的方向坐标。这不是很好求(不是直接加负号这么简单)。但是如果是世界空间下的观察空间的基的方向坐标,则是直接就可以得到的。而这两个基的变换矩阵之间的关系其实就是逆矩阵的关系。所以从世界空间变换到观察空间的变换矩阵我们也得到了。
下面是P投影变换,分为正交投影和透视投影。

如右图是一个简单的正交投影的理解。首先把相机按y上-z前的方向摆好。然后把所有物体丢掉z轴即可。然后把x,y的范围映射到-1到1方便运算。但是丢掉z轴,怎么判断谁前谁后呢?

所以我们用的是一种正规的正交投影方法。首先划定空间中一个长方体,通过平移和缩放操作变成一个以原点为中心,长宽高为2的正方体。
我刚开始也有这个疑惑?为什么要专门划定一个区域,还要平移?难道不是直接往-z截取一个区域吗。后来参考一些资料后得出结论,这个长方体其实就是可视区域,之所以有平移缩放,就是为了方便相机修改可视区域。总之,这个正交投影的操作就是,划定一个视野范围,然后标准化这个区域。

然后是透视投影。想要理解这个我得先解释清楚MVP的整个过程。一开始我以为它的输入是一个三维空间,输出是一个二维平面,即投影变换后的近平面。但是后来搜资料后才明白,它的输出也是一个三维空间,叫做标准视体空间(更有名一点的说法似乎是叫裁剪空间Clip Space)(就正交投影最终得出来的那个正方体)(其实在不同的图形API里面,标准视体空间的坐标范围也不一样)。裁剪空间的坐标是一个四维齐次坐标系,空间中的物体在此状态下进行裁剪剔除等操作后,再通过透视除法(perspective divide)降维成三维的笛卡尔坐标系,而这个降维后的坐标系就叫做标准设备坐标(Normalized Device Coordinate),这个空间也叫NDC(规范化设备坐标)空间。之后对于NDC内的几何体,再做一个变换,得到它们在屏幕空间的坐标。这时候才可以说结果是一个二维平面了。但是要注意,这个屏幕映射只是单纯的从三维到二维的变换,不涉及绘制,也就是说没有什么遮挡关系之类的。几何体的深度信息会被保存在深度缓存中,在后面的光栅化过程中再用来决定遮挡关系。
好,介绍完整个流程后,我再来说这个透视投影。投影变换的本质是把物体从观察空间变换到裁剪空间。正交投影可以很方便的拉伸视体(那个长方体)为一个裁剪空间(最终的正方体)。而透视投影则要从一个视锥体(棱台)拉伸为一个正方体。因此我们考虑这个步骤,先把它拉伸为一个长方体,再做正交投影变换。这个长方体有两个原则:近平面大小和坐标不变,远平面的z值和中心点位置不变,四周的点压缩到和近平面一样大。


那么这样子,我们就可以确定所有平面的压缩后的xy的值了。如图,假设这个平面到原点距离是n(特别注意是距离不是z值,而且是变换前的距离)然后远平面到原点的距离是z,那么这个平面的压缩后的x'y',就是如图所示。

而知道变换前后的坐标后,我们就可以求出变换矩阵了。但是目前只能确定124行,第三行确定不了。因为我们之前只是确定了平面压缩后的xy值,但平面的z值没确定过。(注意我们之前只是设定远近平面的z值不变,而中间这些平面的z值是否有变动我们是没说过的,而事实上,它们的z值确实有变动)

那么我们要如何求这个变换矩阵的第三行呢?很简单,带入前面那两个特例。对于近平面来说,映射后坐标值毫无变化。求得如图中式子(假设n为近平面到原点距离,near嘛)。

而对于远平面来说,则是中心点映射后坐标不变,求得图中式子。(f为远平面到原点距离,far)

n,f都是已知的,未知量就AB,两个未知量,两个式子,很容易解方程。至此,投影变换的矩阵就求出来了。

而最后值得我们思考的一个点是,在远近平面中间的平面,它们的z值是怎么变化的呢?我先直接根据经验猜测一下。如图,对于一张透视的图,相同的间隔在图里面是随着距离的增大而变短的。这意味着什么?我们想象一下这个空间,应该不难想出它会发生如右图的变换:越靠近n越接近原来的距离,越靠近f间隔越密。


也就是说整体上,中间平面的z值往远平面那边偏了。
下面我尝试数学证明。证明了半天感觉有点难,遂放弃。在gpt帮助下找到个优秀答案,不过也证实了我的猜想是正确的。
