学习Shader所需的数学基础(矩阵)

在三维数学中,咱们一般会使用矩阵来进行变换。一个矩阵能够把一个矢量从一个坐标空间转换到另外一个坐标空间。函数

矢量和矩阵

咱们能够用矩阵来表示矢量。实际上,矢量能够当作是n×1的列矩阵或1×n的行矩阵,其中n对应了矢量的维度。
把矢量和矩阵联系在一块儿的缘由是为了让矢量能够像一个矩阵同样参与矩阵的运算。学习

矩阵的运算

矩阵和标量的乘法

矩阵和标量相乘,结果仍然是一个相同维度的矩阵
它们之间的乘法很是简单,就是矩阵的每一个元素和该标量相乘。spa

公式

4034e8bf-d463-4c8b-903c-b3b85409b08f.jpg

矩阵和矩阵的乘法

一个r×n的矩阵A和一个n×c的矩阵B相乘,它们的结果AB将会是一个r×c大小的矩阵。这意味着,矩阵相乘,第一个矩阵的列数必须和第二个矩阵的行数相同。3d

公式

设两个矩阵A和B相乘的结果是矩阵C,那么,C中的每个元素Cij等于A的第i行所对应矢量和B的第j列所对应矢量的点积
74b1c181-1da4-4695-8a1b-4eff1f3c5b62.jpg
以一个简单的方式解释:对于每一个元素Cij,咱们找到A中的第i行和B中的第j列,而后把他们的对应元素相乘后再加起来,这个和就是Cijcode

性质

  • 矩阵乘法不知足交换律
  • 矩阵乘法知足结合律

ae0c0fea-295b-4320-96c2-cd1de7af12a3.png

方块矩阵

方块矩阵,简称方阵,是指那些行和列数目相等的矩阵。在三维渲染里,最常使用的就是3×3和4×4的方阵
方阵的对角元素指的是行号和列号相等的元素。
若是一个矩阵除了对角元素外的全部元素都为0,那么这个矩阵就叫作对角矩阵
一个4×4的对角矩阵:
9fc264f6-434f-47ac-bc0d-b59a4e7179c0.pngblog

单位矩阵

若是一个对角矩阵的对角元素都为1,那么这个矩阵被称为单位矩阵。一个3×3的单位矩阵以下所示:
78ed8a68-fcf1-4511-86cb-04f48bbdb34c.png
任何矩阵和单位矩阵相乘的结果都仍是原来的矩阵。这就跟标量中的1同样。
0946767c-8e27-4b04-a31c-e0a97a3fad1b.png游戏

转置矩阵

转置矩阵其实是经过对原矩阵进行转置运算获得的。给定一个r×c的矩阵M,它的转置矩阵能够表示成MT,这是一个c×r的矩阵。转置运算就是把原矩阵翻转一下,即原矩阵的第i行变成了第j列,而第j列变成了第i行。
若是一个矩阵的转置矩阵是其自己,则咱们称其为对称矩阵游戏开发

公式

44f3d869-7431-4830-baff-6800e7d85efb.png
对于行矩阵和列矩阵来讲,咱们可使用转置运算来相互转换:
e013e806-06d2-48b0-8d8c-c9fb7eadeb02.png开发

性质

  • 矩阵转置的转置等于原矩阵

6534bf11-41b1-4c80-918c-a5f5eb9c6e9b.png

  • 矩阵的串接的转置,等于反向串接各个矩阵的转置。这个性质能够扩展到更多矩阵相乘的状况

ae5932c4-0b3e-442d-95df-4586a21f9e61.png

矩阵的行列式

矩阵M的行列式用|M|表示数学

公式

对于2×2矩阵:
659fffd1-922b-4795-b339-2e5f59699091.png
对于3×3矩阵,能够展开为2×2矩阵:

$$ A = \left[ \begin{matrix} a & b & c\\ d & e & f \\ g & h & i \end{matrix} \right] $$

a0a2da5d-2549-4082-b1f5-6bfa6b25c303.png
同理,对于4×4矩阵,能够展开为3×3矩阵:

$$ A = \left[ \begin{matrix} a & b & c & d\\ e & f & g & h\\ i & j & k & l\\ m & n & o & p \end{matrix} \right] $$

271631ed-fc5d-4a8f-a769-b56102705d79.png
能够理解为对于矩阵第一行的每一个元素,都乘以去除该元素所在行和列后剩下矩阵的行列式,而后把结果按照+ -+-的规律加/减起来。

逆矩阵

给定一个方阵M,它的逆矩阵用M-1来表示。逆矩阵最重要的性质就是把M和M-1相乘,那么它们的结果将会是一个单位矩阵
只有方阵才有逆矩阵,且并非全部的方阵都有逆矩阵。
如何判断一个矩阵是否可逆:若是一个矩阵的行列式不为0,那么它就是可逆的。
例如全部元素都为0的方阵就没有逆矩阵
若是一个矩阵有对应的逆矩阵,咱们就说这个矩阵是可逆的或者说是非奇异的。不然这个矩阵就是不可逆的或者说是奇异的

公式

8077a364-5f87-4443-9322-712c552abed7.png

性质

  • 逆矩阵的逆矩阵是原矩阵自己

eaf59fe6-3e92-471a-9897-3455f417f00d.png

  • 单位矩阵的逆矩阵是它自己

e851b541-8a9a-440e-a867-7be488ae9630.png

  • 转置矩阵的逆矩阵是逆矩阵的转置

3a34e126-cc7a-41a1-9544-3f0c30c3d664.png

  • 矩阵串接相乘后的逆矩阵等于反向串接各个矩阵的逆矩阵。这个性质能够扩展到更多矩阵相乘的状况

4b4a5a3f-a9bd-4ca0-887f-58dce852e150.png

逆矩阵是有几何意义的,一个矩阵能够表示一个变换,而逆矩阵容许咱们还原这个变换。假设,咱们使用变换矩阵M对矢量进行了一次变换,而后再使用M的逆矩阵M-1进行另外一次变换,那么咱们会获得原来的矢量。

正交矩阵

若是一个方阵M和它的转置矩阵的乘积是单位矩阵的话,咱们就称这个矩阵是正交的
再结合逆矩阵的公式,咱们能够知道,若是一个矩阵是正交的,那么它的转置矩阵和逆矩阵是同样的

公式

6cca82c6-d906-4adf-9c81-eafe53f95ba3.png
a738cb34-a871-463a-a8dd-0a865d0f7ba0.png
在三维变换中,咱们常常会使用逆矩阵来求解反向的变换。但逆矩阵的求解每每计算量很大,而若是咱们能够肯定这个矩阵是正交矩阵的话,就能够直接经过转置矩阵获得逆矩阵。
那么如何判断的一个矩阵是不是正交矩阵呢,固然能够经过公式计算判断,但这仍然须要必定的计算量,有时候咱们更但愿不经过计算,而根据一个矩阵的构造过程来判断这个矩阵是不是正交矩阵
根据正交矩阵的定义能够获得:
be98a6c7-3a25-4062-be29-6e2e8a9981d6.png
这样,咱们就有个9个等式:
27be4ee2-cf91-43ef-b6bc-4cf6f9169412.png
能够获得以下结论:

  • 矩阵的每一行(即c1,c2,c3)都是单位矢量,由于它们与本身的点积为1
  • 矩阵的每一行(即c1,c2,c3)都互相垂直,由于它们互相的点积为0(参考点积的公式|a||b|cosθ)
  • 上述的两条结论对每一列也一样适用。由于M是正交矩阵的话,MT也是正交矩阵

也就说若是一个矩阵知足上面的条件,那么它就是一个正交矩阵。

行矩阵仍是列矩阵

因为一个矢量既能够转换成一个行矩阵也能够转换成列矩阵,虽然它们自己是没有区别的,但当咱们须要把它和另外一个矩阵相乘时,就会出现差别,由于矩阵的乘法是不知足交换律的。
在Unity中,常规作法是把矢量放在矩阵的右侧,即把矢量转换成列矩阵来进行计算。此时咱们的阅读顺序是从右到左的。即对矢量v先使用A进行变换,再使用B进行变换,最后使用C进行变换。
95eeaa2f-3da3-44d3-a3c7-2891629e9a75.jpg

矩阵的几何意义:变换

在游戏的世界中,变换通常包含了旋转,缩放和平移。游戏开发人员但愿给定一个点或矢量,再给定一个变换,就能够经过某个数学运算来求得新的点和矢量。而使用矩阵能够完美地解决这个问题。

什么是变换

变换指的是咱们把一些数据,如点,方向矢量,甚至是颜色等,经过某种方式进行转换的过程。
线性变换指的是那些能够保留矢量加和标量乘的变换。用数学公式来表示这两个条件就是:
03cdfd38-3890-49b0-a01c-c18aa12a2950.png
缩放就是一种线性变换,例如f(x) = 2x,能够表示一个大小为2的统一缩放
旋转也是一种线性变换
若是咱们要对一个三维的矢量进行线性变换,那么仅仅使用3×3的矩阵就能够表示全部的线性变换。
线性变换除了包括旋转和缩放外,还包括错切,镜像(反射),正交投影等。
仿射变换就是合并线性变换和平移变换的变换类型。仿射变换可使用一个4×4的矩阵来表示。

齐次坐标

因为3×3矩阵不能表示一个平移操做,咱们就将其扩展到了4×4的矩阵。为此,咱们还须要把原来的三维矢量转换成四维坐标,也就是齐次坐标(齐次坐标的维度能够超过四维,但本文泛指四维齐次坐标)。
如何把一个三维矢量转换成四维矢量呢:

  • 对于一个点,从三维坐标转换成齐次坐标就是把w份量设置为1
  • 对于方向矢量,须要把w份量设置为0。这样当用4×4矩阵进行变换时,平移的效果会被忽略(由于方向矢量没有位置)。

基础变换矩阵

咱们把表示纯平移,纯旋转和纯缩放的变换矩阵叫作基础变换矩阵
咱们能够把一个基础变换矩阵分解成4个组成部分:

$$ \left[ \begin{matrix} M_{3×3} & T_{3×1}\\ 0_{1×3} & 1 \end{matrix} \right] $$

其中,左上角的矩阵M3×3表示旋转和缩放,T3×1表示平移,01×3是零矩阵,右下角的元素是标量1(第四行是(0 0 0 1)的缘由是保证w份量保持不变)。

平移矩阵

咱们可使用矩阵乘法来表示对一个点进行平移变换,以下所示,从结果很容易看出这个矩阵为何有平移效果:点的x, y, z份量分别增长了一个位置偏移,即把点(x, y, z)在空间中平移了(tx, ty, tz)个单位。
0a0c6810-97b3-42e4-b8d7-11520e21f594.png
对一个方向矢量进行平移变换,不会对其产生任何影响:
d1701cf2-c007-43bf-815f-6dc6a53c8832.png
平移矩阵的逆矩阵就是反向平移获得的矩阵。能够看出平移矩阵并非一个正交矩阵。
4a9170ef-f25b-438d-a2aa-57af324499a7.png

缩放矩阵

咱们可使用矩阵乘法来表示一个缩放变换:
1d562efb-2f98-440f-895b-8adaff503f13.png
对方向矢量一样能够进行缩放:
ff3556cd-3fcb-4dfb-82fc-a661378daee0.png
若是缩放系数Kx = Ky = Kz,咱们把这样的缩放称为统一缩放,不然称为非统一缩放。从外观上看,统一缩放是扩大整个模型,而非统一缩放会挤压或拉伸模型,改变与模型相关的角度和比例。
缩放矩阵的逆矩阵是使用原缩放矩阵系数的倒数来进行缩放,缩放矩阵通常也不是正交矩阵。
969e677b-f4f9-4f9d-9c80-ddf1942edc8b.png

旋转矩阵

在学习三维空间下的旋转矩阵前,咱们先来看一下二维空间下的旋转,向量v旋转θ度,获得v':
4347fce3-f880-4b17-8ff3-acdfe8b61f09.png
假设v的模为r,则旋转前v的x = r * cosΦy = r * sinΦ
旋转后v'的x' = r * cos( Φ + θ )y' = r * sin( Φ + θ )
根据三角函数的展开公式:

$$ cos( Φ + θ ) = cosΦ*cosθ - sinΦ*sinθ\\ sin( Φ + θ ) = sinΦcosθ + sinθ*cosΦ $$

可得v'的x' = x*cosθ - y*sinθy' = x*sinθ + y*cosθ,即
b26deaf3-fce8-40c5-9557-48df9910d731.png
让咱们再回到三维空间,上面的二维旋转,能够理解为在三维中绕z轴的旋转正方向进行旋转(读者能够想象在左手坐标系下,对于上图的二维旋转,z轴正方向是指向屏幕内部的,根据左手法则,绕z轴旋转的正方向就是由x到y)
所以,三维空间下的绕z轴的旋转矩阵以下所示,由于绕z轴旋转,因此z坐标应该是保持不变的。
ac1f686c-a9c7-4ec4-a3ab-957099178952.png
同理,绕x轴的旋转以下所示:
ea82f69e-2690-48ba-b4d1-7d98cbe12fdf.png
绕y轴的旋转以下所示:
1230486e-7740-46b2-8aea-6bc02715ddd0.png

旋转矩阵是正交矩阵,所以旋转矩阵的逆矩阵等于其转置矩阵。并且多个旋转矩阵之间的串联一样是正交的

复合变换

咱们能够把平移,旋转和缩放组合起来,造成一个复杂的变换过程。复合变换能够经过矩阵的串联来实现。例如:
5d777cca-6ffa-4e8b-9720-d2d746caf51f.png
因为矩阵乘法不知足交换律,所以矩阵乘法的顺序很重要。在大多数状况下,咱们约定变换的顺序是先缩放,再旋转,最后平移。
除了须要注意不一样类型的变换顺序外,还须要当心旋转的变换顺序。若是咱们须要同时绕着3个轴进行旋转,那么应该按什么样的旋转顺序呢?
在Unity中,这个旋转顺序是zxy
旋转时使用的坐标系也有如下两种选择:

  • 绕坐标系E下的z轴旋转θz,绕坐标系E下的x轴旋转θx,绕坐标系E下的y轴旋转θy
  • 绕坐标系E下的z轴旋转θz后,坐标系也绕z轴旋转θz,新的坐标系记作E'。再在E'下绕x轴旋转θx,坐标系也作一样的旋转,记作E''。再在E''下,绕y轴旋转θy。即旋转的时候,坐标系也一块儿转动。

上述两种状况的结果是不同的,但若是把它们的顺序颠倒一下,获得的结果就会是同样的。
对于第二种状况,yxz旋转顺序的变换矩阵是M = Mrotate_z Mrotate_x Mrotate_y,则对于第一种状况,zxy的旋转矩阵也是M = Mrotate_z Mrotate_x Mrotate_y。Untiy的zxy旋转顺序指的就是在第一种状况下旋转的顺序。

相关文章
相关标签/搜索