前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Unity Shader入门精要》笔记(三)

《Unity Shader入门精要》笔记(三)

作者头像
代码咖啡
发布2021-12-06 17:45:15
1.2K0
发布2021-12-06 17:45:15
举报
文章被收录于专栏:程序员叨叨叨

本文记录《第4章 学习Shader所需的数学基础》的矩阵基础知识内容。

笛卡尔坐标系

二维笛卡尔坐标系

二维笛卡尔坐标系:

  • 原点
  • x轴、y轴(基矢量)

x轴、y轴朝向并非固定,如:OpenGL和DirectX使用了不同的二维笛卡尔坐标系。

三维笛卡尔坐标系

三维笛卡尔坐标系:

  • 原点
  • x轴、y轴、z轴(基矢量)

标准基矢量:互相垂直,且长度为1的基矢量。 正交基:互相垂直,但长度不为1的基矢量。

左手坐标系和右手坐标系

以手的大拇指作为+x轴,食指作为+y轴,中指作为+z轴,将3根手指互相垂直,可以用左手示意的坐标系,为左手坐标系:

可以用右手示意的坐标系,为右手坐标系:

左手坐标系和右手坐标系无法通过旋转实现坐标轴指向重合。

左手坐标系和右手坐标系分别对应左手法则右手法则,用来在坐标系中定义旋转的正方向,下图4个手指指向的方向即为正方向:

Unity使用的坐标系

Unity的模型空间和世界空间使用的是左手坐标系,注意观看下图红、绿、蓝轴在右上角分别对应x轴、y轴、z轴:

Unity的观察空间使用的是右手坐标系。观察空间,就是以摄像机作为原点的坐标系,在这个坐标系中,摄像机的前向是z轴的负方向,与模型/世界空间的定义相反。即:z轴坐标的减少意味着场景深度的增加。

点和矢量

点是n维空间(游戏中主要是用二维、三维空间)中的一个位置,没有大小、宽度的概念。 二维空间点的表示:p = (x, y) 三维空间点的表示:p = (x, y, z)

矢量是n为空间中包含模和方向的有向线段,没有位置的概念。 矢量的模:矢量的长度,非负数。 矢量的方向:矢量在空间中的指向。 矢量的表示与点类似,v = (x, y),v = (x, y, z),v = (x, y, z, w)

为区分点和矢量,在变量书写上,标量用小写字母表示,如:a, b, x, y, z等;矢量用小写的粗体字母表示,如:a, b, u, v等。

矢量通常有一个箭头表示:

矢量和标量的乘法/除法

标量是只有模,没有方向的量,比如:距离、速度等。 矢量无法与标量进行加减运算,但是可以进行乘法或除法运算。

矢量与标量的乘法: kv = (kvx, kvy, kvz)

矢量可以被非0的标量除,但是矢量无法作为除数:

从几何意义上看,一个矢量v和一个标量k相乘,意味着对矢量v进行一个大小为|k|的缩放。若k<0,则矢量方向取反,如下图:

矢量的加法和减法

两个矢量加减,即:两个矢量的对应分量进行加减,公式如下: a + b = (ax+bx, ay+by, az+bz) a - b = (ax-bx, ay-by, az-bz)

从几何意义上看,矢量加法,即:把矢量a的头连接到矢量b的尾,然后画一条从a的尾到b的头的矢量,来得到ab相加后的矢量,如下图所示:

也可以理解为:一个点从a的尾进行位置偏移a,在进行位置偏移b,就等同于进行了a+b的位置偏移,这被称为矢量加法的三角形定则

矢量的减法类似:

在图形学中,矢量通常用于描述位置偏移(简称位移)。我们可以利用矢量的加法和减法来计算一点相对于另一点的位移。

矢量的模

矢量的模是一个标量,可以理解为矢量在空间中的长度。表示符号通常是在矢量的两边加上竖线,比如:|v|。

三维矢量的模的计算公式:

其他维度的矢量的模计算类似,都是对每个分量平方相加后开根号。几何意义,可用下图解释:

单位矢量

单位矢量指模为1的矢量,也被称为被归一化的矢量(normalized vector)。通常用在只关心方向,不关心模的矢量,比如:模型的发现方向、光源方向等。

把非零矢量转换成单位矢量的过程叫归一化。 单位矢量的表示为:

单位矢量的公式:

零矢量:每个分量的值都为0的矢量,如:v = (0, 0, 0)。零矢量不能被归一化,因为除法运算时,分母不能为0。

从几何意义上看,对于二维空间,单位矢量就是从圆心出发、到圆边界的矢量:

对于三维空间,单位矢量就是从圆心出发、到球面的矢量。

在Unity Shader中,会经常遇到法线方向、光源方向,这些矢量不一定是归一化后的矢量,计算的时候需要将这些矢量归一化成单位矢量。

矢量的点积

矢量的乘法有两种类型:点积(dot product)、叉积(cross product)。

矢量的点积,也叫内积。点积的运算表示:a·b,中间的点不能省略。

点积公式一a·b = (ax, ay, az) · (bx, by, by) = axby + ayby + azbz

点积满足交换律: a·b = b·a

点积的几何意义:投影

投影的值可能是负数,投影结果的正负号与ab两个矢量的方向有关:方向相反,结果小于0;方向相同,结果大于0;方向垂直,结果等于0。

性质一: 点积可结合标量乘法 (kab = a·(kb)=k(a·b) k的几何意义是:对矢量进行缩放。

性质二: 点积可结合矢量加减法 a·(b+c) = a·b + a·cc换成-c就是减法的版本。

性质三: 一个矢量与自身点积的结果是该矢量模的平方 v·v = vxvx + vyvy + vzvz = |v|2 可以用矢量点积的形式来求矢量的模,Shader中常用模的平方来直接做比较或运算,目的是减少开放带来的性能消耗。

点积公式二a·b = |a||b|cosθ

公式二的证明: 假设对两个单位矢量进行点积

如下图所示:

由上图可知,cosθ对应的直角边是:a·b的点积(b矢量在a矢量的投影),且cosθ = 直角边 / 斜边,则a·b的点积 = cosθ * 斜边,因为单位矢量b的模是1(斜边长度为1),所以:a·b的点积 = cosθ,也就是两个单位矢量的点积为夹角的cos值。

再由之前性质一,可得推导公式二:

由公式二可知,点积可用于求两个矢量的夹角:

矢量的叉积

叉积,也叫外积。与点积不同,叉积的结果仍然是矢量,而非标量。

叉积的表示:a x b,叉号不能省略。叉积的计算公式如下: a x b = (ax, ay, az) x (bx, by, bz) = (aybz-azby, azbx-axbz, axby-aybx)

具体的记法,可以这样:

  1. 先看每个分量的被减数 aybz、azbx、axby,它们下标的规律是不包含当前分量下标,比如:x分量的被减数只有y、z下标,y分量的被减数只有x、z下标,z分量的被减数只有x、y下标。
  2. 然后看被减数中a的下标 ay、az、ax,a的下标永远是当前分量的下一个,比如:x分量的下标是y,y分量的下标是z,z分量的下标是x。
  3. 再看被减数中b的下标 bz、bx、by,b的下标永远和a不一样,再结合第1点记忆,b的下标不是当前分量,所以x分量b的下标只能是除了x以外的y、z的其中一个,而y被a用了,所以b的下标只能是z,其他分量的b以此类推。
  4. 再看每个分量的减数 azby、axbz、aybx,他们的下标就是被减数中a和b下标的互换,所以aybz的减数是azby,其他以此类推。

叉积不满足交换律,即:a x bb x a;但是叉积满足反交换律,即:a x b = - (b x a)。 叉积不满足结合律,即:(a x b) x ca x (b x c)。

叉积的几何意义: 对两个矢量进行叉积的结果,会得到同时垂直于这两个矢量的新矢量。

叉积的模 公式: |a x b| = |a||b|sinθ

这容易联想到平行四边形求面积:

面积A = |b| h = |b| (|a| sinθ) = |a||b|sinθ

叉积的方向 从几何意义可知,两个矢量的叉积,会得到垂直于两个矢量的新矢量,但是与其垂直的有两个向量。这时前面学到的左/右手坐标系就派上用场了,它用来确定叉积得到新矢量的方向朝哪边。

将大拇指与a同向,食指与b同向,中指指向的方向就是叉积结果的方向,所以使用左、右手就会得到不同的朝向,如下图:

同理,左右手法则也通用可以用来判断,如下图:

矩阵

矩阵的定义

矩阵(Matrix),就是有m x n个标量组成的长方形数组,通常用方括号在左右两侧围住这些数字,大概像这样:

有些资料也会用圆括号或花括号,其实都一样的。

矩阵有行、列之分,上图的数组就是三行四列。以3x3矩阵为例,它可以写成:

mij表示这个元素在矩阵M的第i行、第j列。

和矢量联系起来

矢量,我们通常写成:a = (x, y, z),可以看出矢量与矩阵一样,也是个数组。将矢量按照矩阵的写法,可以看成是n x 1的列矩阵或1 x n的行矩阵,n对应矢量的维度。

以矢量v = (3, 8, 6)举例,写成行矩阵: [3, 8, 6]

写成列矩阵:

为什么要和矢量联系起来?因为Shader中经常会将法线(矢量)进行坐标变换,而坐标变换是矩阵的几何意义,所以需要运用矩阵的运算来将法线从模型空间转变成世界空间。(后续会学到)

矩阵运算

矩阵和标量的乘法

与矢量类似,矩阵和标量相乘后,结果仍然是一个矩阵。公式如下:

矩阵和矩阵的乘法

矩阵和矩阵相乘后,结果也是矩阵。新的矩阵的维度与两个原矩阵的维度有关。一个rxn的矩阵A和一个nxc的矩阵B相乘后,得到的结果AB是一个rxc大小的矩阵。需要注意,第一个矩阵的列数必须和第二个矩阵的行数相等,才能相乘

比如:矩阵A的维度是4x3,矩阵B的维度是3x6,则AB的维度是4x6

矩阵乘法的表达式: 假设有rxn的矩阵A和nxc的矩阵B,相乘后得到一个rxc的矩阵C = AB,那么C中的每个元素Cij等于A的第i行所对应的矢量和B的第j列所对应的矢量进行点乘的结果,即:

简单解释为: 对于每个元素cij,找到A中的第i行和B中的第j列,把他们对应的元素相乘后再加起来,这个和就是cij。

性质一: 矩阵乘法不满足交换律:AB ≠ BA

性质二: 矩阵乘法满足结合律:(AB)C = A(BC)ABCDE = ((A(BC))D)E = (AB)(CD)E

特殊的矩阵

方块矩阵

方块矩阵,简称方阵。指行数和列数相等的矩阵,比如:3x34x4的矩阵。

方块矩阵独有的:对角元素——行号和列号相等的元素。只有对角元素非0的矩阵叫对角矩阵

单位矩阵

对角元素都为1的对角矩阵,叫做单位矩阵,用In表示,比如:

单位矩阵特性:任何矩阵和它相乘的结果还是原来的矩阵。相当于标量中1的地位。 MI = IM = M

转置矩阵

转置矩阵实际是对原矩阵的一种运算,即转置运算。一个rxc的矩阵M,其转置表示成MT,是一个cxr的矩阵,本质是原来的矩阵行、列对换。

性质一: 矩阵转置的转置等于原矩阵。 (MT)T = M

性质二: 矩阵串联的转置,等于反向串联各个矩阵的转置。 (AB)T = BTAT

逆矩阵

只有方阵才有逆矩阵,逆矩阵表示为M-1。一个矩阵与它的逆矩阵相乘,结果是一个单位矩阵: MM-1 = M-1M = I 有点标量里面倒数的味道。

不是所有方阵都有对应逆矩阵,比如:所有元素都为0的矩阵。 如果一个矩阵有对应的逆矩阵,则它是可逆的非奇异性的; 相反,则它是不可逆的奇异性的

判断矩阵是否可逆: 矩阵的行列式不为0,则它是可逆的。 参考视频链接:https://www.bilibili.com/video/BV1aW411Q7x1?p=2

性质一: 逆矩阵的逆矩阵是原矩阵本身。 (M-1)-1 = M

性质二: 单位矩阵的逆矩阵是它本身。 I-1 = I

性质三: 转置矩阵的逆矩阵是逆矩阵的转置。 (MT)-1 = (M-1)T

性质四: 矩阵串联相乘后的逆矩阵等于反串联各个矩阵的逆矩阵。 (AB)-1 = B-1A-1 (ABCD)-1 = D-1C-1B-1A-1

矩阵的几何意义是变换,逆矩阵表示还原这个变换,或这个变换的反向变换。 使用变化矩阵M对矢量v进行一次变换,然后再使用逆矩阵M-1进行一次变换,会得到原来的矢量v。 M-1(Mv) = (M-1M)v = Iv = v

正交矩阵

正交矩阵是特殊的方阵。一个方阵M和它的转置矩阵的乘积是单位矩阵,则这个矩阵是正交的。 MMT = MTM = I

有逆矩阵的性质MM-1 = M-1M = I可以得出正交矩阵的逆矩阵是它的转置矩阵: MT = M-1

正交矩阵可以用转置矩阵的运算代替逆矩阵的运算,因为逆矩阵计算更复杂。

怎样判定一个矩阵是正交矩阵?来看一下它有哪些定义。

因为:

所以:

于是可以得到以下结论:

  • 矩阵的每一行,即c1、c2、c3是单位矢量;(因为他们与自己的点积是1)
  • 矩阵的每一行,即c1、c2、c3之间相互垂直;(因为他们的点积是0)
  • 上述两条,对矩阵的每一列同样适用;(因为正交矩阵的转置通用是正交矩阵)

行矩阵还是列矩阵

一个矢量(比如:平行光的方向、表面发现方向),既可以写成行矩阵的形式,也可以写成列矩阵的形式,但是当它和矩阵相乘时,使用行矩阵还是列矩阵对其乘法的书写次序和结果值是有影响的。

假设有一个矢量v = (x, y, z),写成行矩阵是:v = [x y z],写成列矩阵是:v = [x y z]T(这里使用转置符号表示列矩阵的写法,纯粹为了排版)。另外有一个矩阵M:

当M和行矩阵相乘时,写法为: vM = [xm11+ym21+zm31 xm12+ym22+zm32 xm13+ym23+zm33]

当M和列矩阵相乘时,写法为:

可以看到两者相乘的书写次序和结果里面元素也是不一样的。

Unity中通常把矢量当做列矩阵,所以相乘时,矢量是放在矩阵的右侧的,且阅读顺序也是从右到左。例如: CBAv = (C(B(Av))) 表示先对v进行A矩阵变换,再进行B矩阵变换,最后进行C矩阵变换。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 笛卡尔坐标系
    • 二维笛卡尔坐标系
      • 三维笛卡尔坐标系
        • 左手坐标系和右手坐标系
          • Unity使用的坐标系
          • 点和矢量
            • 矢量和标量的乘法/除法
              • 矢量的加法和减法
                • 矢量的模
                  • 单位矢量
                    • 矢量的点积
                      • 矢量的叉积
                      • 矩阵
                        • 矩阵的定义
                          • 和矢量联系起来
                            • 矩阵运算
                              • 矩阵和标量的乘法
                              • 矩阵和矩阵的乘法
                              • 特殊的矩阵
                              • 行矩阵还是列矩阵
                          相关产品与服务
                          对象存储
                          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档