Unity系列文章目录

文章目录

  • Unity系列文章目录
  • 前言
  • 4.4.3 矩阵运算
    • 4.4.4 特殊的矩阵
    • 2.单位矩阵
  • 参考

前言

不幸的是,没有人能告诉你母体(matrix)究竟是什么。你需要自己去发现它。
—电影《黑客帝国》(英文名:The Matrix)
矩阵,英文名是matrix。如果你用翻译软件去查matrix 这个单词的翻译,就会发现它还有一
个意思就是母体。事实上,很多人都不知道,那部具有跨时代意义的电影《黑客帝国》的英文名
就是《The Matrix》。在电影《黑客帝国》中,母体是一个庞大的虚拟系统,它看似虚无缥渺,但
又连接万物。这一点和矩阵有异曲同工之妙。
没有人敢否认矩阵在三维数学中的重要性,事实上矩阵在整个线性代数的世界中都扮演了举
足轻重的角色。在三维数学中,我们通常会使用矩阵来进行变换。一个矩阵可以把一个矢量从一
个坐标空间转换到另一个坐标空间。在第2 章渲染流水线中,我们就看到了很多坐标变换,例如
在顶点着色器中我们需要把顶点坐标从模型空间变换到齐次裁剪坐标系中。而在这一章中,我们
先来认识一下矩阵这个概念。
那么,现在我们就来看一下,这些放在一个小括号里的数字怎么就这么重要呢?为什么数学
家们都喜欢用这个小东西来搞出这么多名堂呢?
4.4.1 矩阵的定义
相信很多读者都见过矩阵的真容,例如像下面这个样子:

从它的外观上来看,就是一个长方形的网格,每个格子里放了一个数字。的确,矩阵就是这
么简单:它是由m×n 个标量组成的长方形数组。在上面的式子中,我们是用方括号来围住矩阵
中的数字,而一些其他的资料可能会使用圆括号或花括号来表示,这都是等价的。
既然是网格结构,就意味着矩阵有行(row)列(column)之分。例如上面的例子就是一个3×4
的矩阵,它有三行四列。据此,我们可以给出矩阵的一般表达式。以3×3 的矩阵为例,它可以写成:

mij 表明了这个元素在矩阵M 的第i 行、第j 列。
这样看起来矩阵也没什么神秘的嘛。但是,越简单的东西往往越厉害,这也是数学的魅力所在。
4.4.2 和矢量联系起来
前面说到,矢量其实就是一个数组,而矩阵也是一个数组。既然都是数组,那就是一家人了!
我们很容易想到,我们可以用矩阵来表示矢量。实际上,矢量可以看成是n×1 的列矩阵(column
matrix)或1×n 的行矩阵(row matrix),其中n 对应了矢量的维度。例如,矢量v=(3,8,6)可以写
成行矩阵


为什么我们要把矢量和矩阵联系在一起呢?这是为了可以让矢量像一个矩阵一样一起参与矩
阵运算。这在空间变换中将非常有用。
到现在,使用行矩阵还是列矩阵来表示矢量看起来是没什么分别的。的确,我们可以根据自
己的喜好来选择表示方法,但是,如果要和矩阵一起参与乘法运算时,这种选择会影响我们的书
写顺序和结果。这正是我们下面要讲到的。

4.4.3 矩阵运算

矩阵这个家伙看起来比矢量要庞大很多,那么它的运算是不是很复杂呢?答案是肯定的。但
是,幸运的是在写Shader 的过程中,我们只需要和很简单的一部分运算打交道。
1.矩阵和标量的乘法
和矢量类似,矩阵也可以和标量相乘,它的结果仍然是一个相同维度的矩阵。它们之间的乘
法非常简单,就是矩阵的每个元素和该标量相乘。以3×3 的矩阵为例,其公式如下:

2.矩阵和矩阵的乘法
两个矩阵的乘法也很简单,它们的结果会是一个新的矩阵,并且这个矩阵的维度和两个原矩
阵的维度都有关系。
一个r×n 的矩阵A 和一个n×c 的矩阵B 相乘,它们的结果AB 将会是一个r×c 大小的矩阵。
请读者注意它们的行列关系,第一个矩阵的列数必须和第二个矩阵的行数相同,它们相乘得到的
矩阵的行数是第一个矩阵的行数,而列数是第二个矩阵的列数。例如,如果矩阵A 的维度是4×3,
矩阵B 的维度是3×6,那么AB 的维度就是4×6。
如果两个矩阵的行列不满足上面的规定怎么办?那么很抱歉,这两个矩阵就不能相乘,因为
它们之间的乘法是没有被定义的(当然,读者完全可以自己定义一种新的乘法,但是数学家们会
不会买账就不一定了)。那么为什么会有上面的规定呢?等我们理解了矩阵乘法的操作过程自然就
会明白。
我们先给出看起来很复杂难懂(当给出直观的表式后读者会发现其实它没那么难懂)的数学
表达式:设有r×n 的矩阵A 和一个n×c 的矩阵B,它们相乘会得到一个r×c 的矩阵C=AB。那
么,C 中的每一个元素cij 等于A 的第i 行所对应的矢量和B 的第j 列所对应的矢量进行矢量点乘
的结果,即
cij=ai1b1j+ ai2b2j+…+ ainbnj=
1
n
ik kj
k
a b
 
看起来很复杂对吗?但是,我们可以用一个更简单的方式来解释:对于每个元素cij,我们找
到A 中的第i 行和B 中的第j 列,然后把它们的对应元素相乘后再加起来,这个和就是cij。
一种更直观的方式如图4.30 所示。假设A 的大小是4×2,B 的大小是2×4,那么如果要计算
C 的元素c23 的话,先找到对应的行矩阵和列矩阵,即
A 中的第2 行和B 中的第3 列,把它们进行矢量点积后
就可以得到结果值。因此, c23=a21b13+a22b23。
在Shader 的计算中,我们更多的是使用4×4 矩阵
来运算的。
矩阵乘法满足一些性质。
性质一:矩阵乘法并不满足交换律。
也就是说,通常情况下:
AB≠BA
性质二:矩阵乘法满足结合律。
也就是说,
(AB)C=A(BC)
矩阵乘法的结合律可以扩展到更多矩阵的相乘。例如,
ABCDE=((A(BC))D)E=(AB)(CD)E
读者可根据矩阵乘法的定义很轻松地验证上述结论。
▲图4.30 计算c23 的过程

4.4.4 特殊的矩阵

有一些特殊的矩阵类型在Shader 中经常见到。这些特殊的矩阵往往具有一些重要的性质。
1.方块矩阵
方块矩阵(square matrix),简称方阵,是指那些行和列数目相等的矩阵。在三维渲染里,最
常使用的就是3×3 和4×4 的方阵。
方阵之所以值得单独拿出来讲,是因为矩阵的一些运算和性质是只有方阵才具有的。例如,
对角元素(diagonal elements)。方阵的对角元素指的是行号和列号相等的元素,例如m11、m22、
m33 等。如果把方阵看成一个正方形的话,这些元素排列在正方形的对角线上,这也是它们名字
的由来。如果一个矩阵除了对角元素外的所有元素都为0,那么这个矩阵就叫做对角矩阵(diagonal
matrix)。例如,下面就是一个4×4 的对角矩阵:

2.单位矩阵

一个特殊的对角矩阵是单位矩阵(identity matrix),用In 来表示。一个3×3 的单位矩阵如下:


为什么要为这种矩阵单独起一个名字呢?这是因为,任何矩阵和它相乘的结果都还是原来的
矩阵。也就是说,

这就跟标量中的数字1 一样!
3.转置矩阵
转置矩阵(transposed matrix)实际是对原矩阵的一种运算,即转置运算。给定一个r×c 的
矩阵M,它的转置可以表示成MT,这是一个c×r 的矩阵。转置矩阵的计算非常简单,我们只需
要把原矩阵翻转一下即可。也就是说,原矩阵的第i 行变成了第i 列,而第j 列变成了第j 行。数
学公式是:

对于行矩阵和列矩阵来说,我们可以使用转置操作来转换行列矩阵:

转置矩阵也有一些常用的性质。
性质一:矩阵转置的转置等于原矩阵。
很容易理解,我们把一个矩阵翻转一下后再翻转一下,等于没有对矩阵做任何操作。即
(MT)T=M
性质二:矩阵串接的转置,等于反向串接各个矩阵的转置。
用公式表示就是:
(AB)T=BTAT
该性质同样可以扩展到更多矩阵相乘的情况。
4.逆矩阵
逆矩阵(inverse matrix)大概是本书讲到的关于矩阵最复杂的一种操作了。不是所有的矩阵
都有逆矩阵,第一个前提就是,该矩阵必须是一个方阵。
给定一个方阵M,它的逆矩阵用M−1 来表示。逆矩阵最重要的性质就是,如果我们把M 和
M-1 相乘,那么它们的结果将会是一个单位矩阵。也就是说,
MM−1= M−1M=I
前面说了,并非所有的方阵都有对应的逆矩阵。一个明显的例子就是一个所有元素都为0 的
矩阵,很显然,任何矩阵和它相乘都会得到一个零矩阵,即所有的元素仍然都是0。如果一个矩
阵有对应的逆矩阵,我们就说这个矩阵是可逆的(invertible)或者说是非奇异的(nonsingular);
相反的,如果一个矩阵没有对应的逆矩阵,我们就说它是不可逆的(noninvertible)或者说是奇
异的(singular)。
那么如何判断一个矩阵是否是可逆的呢?简单来说,如果一个矩阵的行列式(determinant)
不为0,那么它就是可逆的。关于矩阵的行列式是什么以及如何求解一个矩阵的逆矩阵,可以参
见本章的扩展阅读部分。由于这部分内容涉及较多计算和其他定义,本书不再赘述。在写Shader
的过程中,这些矩阵通常可以通过调用第三方库(如C++数学库Eigen)来直接求得,不需要开
发者手动计算。在Unity 中,重要变换矩阵的逆矩阵Unity 也提供了相应的变量供我们使用。关
于这些Unity 内置的矩阵,读者可以在本章的4.8 节找到更详细的解释。
逆矩阵有很多非常重要的性质。
性质一:逆矩阵的逆矩阵是原矩阵本身。
假设矩阵M 是可逆的,那么
(M−1)−1=M
性质二:单位矩阵的逆矩阵是它本身。

I−1=I

性质三:转置矩阵的逆矩阵是逆矩阵的转置。

(MT)−1=(M−1)T
性质四:矩阵串接相乘后的逆矩阵等于反向串接各个矩阵的逆矩阵。

(AB)−1=B−1A−1
这个性质也可以扩展到更多矩阵的连乘,如:
(ABCD)−1=D−1C−1B−1A−1
逆矩阵是具有几何意义的。我们知道一个矩阵可以表示一个变换(详见4.5 节),而逆矩阵允
许我们还原这个变换,或者说是计算这个变换的反向变换。因此,如果我们使用变换矩阵M 对矢
量v 进行了一次变换,然后再使用它的逆矩阵M−1 进行另一次变换,那么我们会得到原来的矢量。
这个性质可以使用矩阵乘法的结合律很容易地进行证明:
M−1(Mv)=(M−1M)v=Iv=v
5.正交矩阵
另一个特殊的方阵是正交矩阵(orthogonal matrix)。正交是矩阵的一种属性。如果一个方阵
M 和它的转置矩阵的乘积是单位矩阵的话,我们就说这个矩阵是正交的(orthogonal)。反过来也
是成立的。也就是说,矩阵M 是正交的等价于:
MMT= MTM=I
读者可能已经看出来,上式和我们在上一节讲到的逆矩阵时遇到的公式很像。把这两个公式
结合起来,我们就可以得到一个重要的性质,即如果一个矩阵是正交的,那么它的转置矩阵和逆
矩阵是一样的。也就是说,矩阵M 是正交的等价于:
MT=M−1
这个式子非常有用,因为在三维变换中我们经常会需要使用逆矩阵来求解反向的变换。而逆
矩阵的求解往往计算量很大,但转置矩阵却非常容易求解:我们只需要把矩阵翻转一下就可以了。
那么,我们如何提前判断一个矩阵是否是正交矩阵呢?读者可能会说,判断MMT=I 是否成立就
可以了嘛!但是,求解这样一个表达式无疑是需要一定计算量的,这些计算量可能和直接求解逆
矩阵无异。而且,如果我们判断出来这不是一个正交矩阵,那么这些花在验证是否是正交矩阵上
的计算就浪费了。因此,我们更想不需要计算,而仅仅根据一个矩阵的构造过程来判断这个矩阵
是否是正交矩阵。为此,我们需要来了解正交矩阵的几何意义。
我们来看一下对于3×3 的正交矩阵有什么特点。根据正交矩阵的定义,我们有:

这样,我们就有了9 个等式:

我们可以得到以下结论:
 矩阵的每一行,即c1、c2 和c3 是单位矢量,因为只有这样它们与自己的点积才能是1;
 矩阵的每一行,即c1、c2 和c3 之间互相垂直,因为只有这样它们之间的点积才能是0。
 上述两条结论对矩阵的每一列同样适用,因为如果M是正交矩阵的话,MT 也会是正交矩阵。
也就是说,如果一个矩阵满足上面的条件,那么它就是一个正交矩阵。读者可以注意到,一
组标准正交基(定义详见4.2.2 节)可以精确地满足上述条件。在4.6.2 节中,我们会使用坐标空
间的基矢量来构建用于空间变换的矩阵。因此,如果这些基矢量是一组标准正交基的话(例如只
存在旋转变换),那么我们就可以直接使用转置矩阵来求得该变换的逆变换。
读者:我被标准正交、正交这些概念搞混了,可以再说明一下是什么意思吗?
我们:读者应该已经知道,一个坐标空间需要指定一组基矢量,也就是我们理解的坐标轴。
如果这些基矢量之间是互相垂直的,那么我们就把它们称为是一组正交基(orthogonal basis)。
但是,它们的长度并不要求一定是1。如果它们的长度的确是1 的话,我们就说它们是一组标准
正交基(orthonormal basis)。因此,一个正交矩阵的行和列之间分别构成了一组标准正交基。但
是,如果我们使用一组正交基来构建一个矩阵的话,这个矩阵可能就不是一个正交矩阵,因为这
些基矢量的长度可能不为1,也就是说它们不是标准正交基。
4.4.5 行矩阵还是列矩阵
我们已经了解了足够多的数学概念,但在学习矩阵的几何意义之前,我们有必要说明一下行
矩阵和列矩阵的问题。
在前面的章节中我们讲到,可以把一个矢量转换成一个行矩阵或是列矩阵。它们本身是没有
区别的,但是,当我们需要把它和另一个矩阵相乘时,就会出现一些差异。
假设有一个矢量v=(x,y,z),我们可以把它转换成行矩阵v= [xyz]或列矩阵v= [x y z]T(这里使
用了转置符号来避免列矩阵在我们的这一行中显得太高)。现在,有另一个矩阵M:


那么M 分别和行矩阵以及列矩阵相乘后会是什么结果呢?我们先来看M 和行矩阵的相乘。
由矩阵乘法的定义可知,我们需要把行矩阵放在M 的左边(还记得吗,矩阵乘法要求两个矩阵的
行列数满足一定条件),即
11 21 31 12 22 32 13 23 33 vM = [xm  ym  zm xm  ym  zm xm  ym  zm ]
而如果和列矩阵相乘的话,结果是:

读者认真对比就会发现,结果矩阵除了行列矩阵的区别外,里面的元素也是不一样的。这就
意味着,在和矩阵相乘时选择行矩阵还是列矩阵来表示矢量是非常重要的,因为这决定了矩阵乘
法的书写次序和结果值。

在Unity 中,常规做法是把矢量放在矩阵的右侧,即把矢量转换成列矩阵来进行运算。因此,
在本书后面的内容中,如无特殊情况,我们都将使用列矩阵。这意味着,我们的矩阵乘法通常都
是右乘,例如:
CBAv  (C(B(Av)))
使用列向量的结果是,我们的阅读顺序是从右到左,即先对v 使用A 进行变换,再使用B 进
行变换,最后使用C 进行变换。
上面的计算等价于下面的行矩阵运算:
vATBTCT  (((vAT )BT )CT )

参考

Unity Shader入门精要
作者:冯乐乐

Unity Shader入门精要--第4 章 学习Shader 所需的数学基础:矩阵相关推荐

  1. Unity Shader入门精要--第4 章 学习Shader 所需的数学基础

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 4.1 背景:农场游戏 4.2 笛卡儿坐标系 4.2.2 三维笛卡儿坐标系 4.2.3 左手坐标系和右手坐标系 4.2.4 Unity ...

  2. Unity Shader入门精要--第4 章 学习Shader 所需的数学基础:点和矢量

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 点和矢量 4.3.1 点和矢量的区别 参考 前言 点(point)是n 维空间(游戏中主要使用二维和三维空间)中的一个位置,它没有大小. ...

  3. Unity Shader入门精要第七章 基础纹理之遮罩纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.实践 参考 前言 遮罩纹理(mask texture)是本章要介绍的最后一种纹理,它非常有用,在很多商业游戏中 都可以见到它的身影. ...

  4. Unity Shader入门精要第四章:学习Shader 所需的数学基础--坐标空间

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.4.6.1 为什么要使用这么多不同的坐标空间 二.4.6.3 顶点的坐标空间变换过程 4.6.4 模型空间 4.6.6 观察空间 4 ...

  5. Unity Shader入门精要——第3章 Unity Shader基础

    Unity Shader入门精要读书笔记系列 第1章 欢迎来到Shader的世界 第2章 渲染流水线 第3章 Unity Shader基础 文章目录 Unity Shader入门精要读书笔记系列 前言 ...

  6. Unity Shader入门精要第3 章 Unity Shader 基础

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.Unity Shader 概述 二.使用步骤 1.3.1.2 Unity 中的材质 2.Unity 中的Shader 3.Unity ...

  7. Unity Shader入门精要第七章 基础纹理 凹凸映射之在世界空间下计算

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.pandas是什么? 二.使用步骤 2.Unity 中的法线纹理类型 参考 前言 现在,我们来实现第二种方法,即在世界空间下计算光照 ...

  8. Unity Shader入门精要第七章 基础纹理渐变纹理

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.渐变纹理是什么 参考 前言 尽管在一开始,我们在渲染中使用纹理是为了定义一个物体的颜色,但后来人们发现,纹理 其实可以用于存储任何表 ...

  9. Unity Shader入门精要 第4章 笛卡尔坐标系 读书笔记

    第4章 学习Shader所需的数学基础-笛卡尔坐标系 注意:图片的来源基本来自作者冯乐乐的GitHub,感谢作者分享 https://github.com/candycat1992/Unity_Sha ...

  10. TA课程笔记01——光照(主要为shader入门精要第六章)

    //老师在这里简单的简述了一下渲染流水线,我在之前的图形学笔记中很详细的讲述了渲染流水线的过程,便不再赘述 //因为老师很详细的将几种常见的光照模型都讲了一遍,但都是美术方向,前面的案例也都缺少代码, ...

最新文章

  1. 【Weiss】【第03章】练习3.7:有序多项式相乘
  2. OpenCV环境搭建(一)
  3. 元素定位(d4-2)
  4. ASC II 完整码表及简介
  5. 如何设置能快速的阅读一本PDF电子书并做笔记?
  6. 浅读艾宾浩斯遗忘曲线
  7. 第四章 维纳滤波原理及自适应算法
  8. 你知道的用户研究方法有哪些? 你认为应该如何进行定性和定量的研究?
  9. javawebJAVAJSP酒店预订系统jsp酒店管理系统jsp民宿预订酒店jsp客房预订系统jsp宾馆客房预订系统
  10. phonegap3.5了结
  11. 特斯拉开火,状告5名前员工、小鹏汽车、Zoox身陷漩涡...
  12. W10系统下 获取 TrustedInstaller 高级权限.
  13. ESP32 文件存储 spiffs
  14. 左偏树(XJT Love Trees,玲珑杯 Round#8 C lonlife 1081)
  15. 初识JavaScript,体验JS的美好
  16. php怎么获得今天的日期,PHP怎么获取今天、昨天、明天的日期-php教程
  17. java 栈队列区别是什么意思_Java实现数据结构栈stack和队列Queue是什么?
  18. [Win10] 代理服务器出现问题或地址有误
  19. python 云服务器 网站
  20. HTTPs SSL CA

热门文章

  1. 论文写作流程图软件_[转载][强烈推荐]论文写作四助手(四个论文写作软件)...
  2. 免费的生成GIF和截屏的PC端小工具
  3. win7不支持新主板键盘鼠标没驱动怎么办?看一篇就够了。
  4. java blocked_Java 线程状态之 BLOCKED
  5. 海贼C语言,PSV海贼无双3金手指代码 (PSVC)
  6. Mac下Idea安装插件后不能启动的问题
  7. X79寨板远程启动计算机,X79旗舰主板评测
  8. 给华南x99打鸡血BIOS教程
  9. 接入华为推送用API给iOS应用发消息时如何获取access_token?
  10. fw300r 虚拟服务器,迅捷FW300R无线宽带路由器怎么开启UPnP