「技美之路 第02篇」图形 1.2.1 向量基础

Game艺视界 2021-05-10 0.1k
这一节的大部分其实都是初高中数学基础,虽是基础,但通过向量(也可称为矢量),我们可以做出想要的效果。比如获取相机到物体的距离用于判断并剔除不可见的物体,获取光照到物体的距离,调节物体的受光照效果等等…

点和矢量

点(point)是n维空间(游戏中主要使用二维和三维空间)中的一个位置,它没有大小、宽度这类概念。在笛卡儿坐标系中,我们可以使用2个或3个实数来表示一个点的坐标,如P=(PxPy)表示二维空间的点,P=(PxPyPz)表示三维空间中的点。

矢量(vector,也被称为向量)的定义则复杂一些。在数学家看来,向量就是一串数字。你可能要问了,点的表达式不也是一串数字吗?没错,但向量存在的意义更多是为了和标量(scalar)区分开来。通常来讲,向量是指n维空间中一种包含了模(magnitude)和方向(direction)的有向线段,我们通常讲到的速度(velocity)就是一种典型的向量。例如,这辆车的速度是向南80km/h(向南指明了向量的方向,80km/h指明了向量的模)。而标量只有模没有方向,生活中常常说到的距离(distance)就是一种标量。例如,我家离学校只有200m (200m就是一个标量)。

具体来讲

?向量的模指的是这个向量的长度。一个向量的长度可以是任意的非负数。

?向量的方向则描述了这个向量在空间中的指向。

向量的表示方法和点类似。我们可以使用v=(x,y)来表示二维向量,用v=(x,y,z)来表示三维向量,用v=(x,y,z,w)来表示四维向量。

为了方便阐述,我们对不同类型的变量在书写和印刷上使用不同的样式。

  • 对于标量,我们使用小写字母来表示,如a,b, x, y, z, 0, a等。
  • 对于向量,我们使用小写的粗体字母来表示,如a,b, u,v等。
  • 对于后面要学习的矩阵,我们使用大写的粗体字母来表示,如A, B, S, M, R等。

在图4.15中,一个向量通常由一个箭头来表示。我们有时会讲到一个向量的头(head)和尾(tail)向量的头指的是它的箭头所在的端点处,而尾指的是另一个端点处,如图4.15所示。

那么一个向量要放在哪里呢?从向量的定义来看,它只有模和方向两个属性,并没有位置信息。这听起来很难理解,但实际上在生活中我们总是会和这样的向量打交道。例如,当我们讲到一个物体的速度时,可能会这样说“那个小偷正在以100km/h的速度向南逃窜”(快抓住他!),这里的“以100km/h的速度向南”就可以使用一个向量来表示。通常,向量被用于表示相对于某个点的偏移(displacement),也就是说它是一个相对量。只要向量的模和方向保持不变,无论放在哪里,都是同一个向量。

点和矢量的区别

回顾一下,点是一个没有大小之分的空间中的位置,而向量是一个有模和方向但没有位置的量。从这里看,点和向量具有不同的意义。但是,从表示方式上两者非常相似。

在上一节中我们提到,向量通常用于描述偏移量,因此,它们可以用于描述相对位置,即相对于另一个点的位置,此时向量的尾是一个位置,那么向量的头就可以表示另一个位置了。而一个点可以用于指定空间中的一个位置(即相对于原点的位置)。如果我们把向量的尾固定在坐标系原点,那么这个向量的表示就和点的表示重合了。图4.16表示了两者之间的关系。

尽管上面的内容看起来显而易见,但区分点和向量之间的不同是非常重要的,尽管它们在数学表达式上是一样的,都是一串数字而已。如果一定要给它们之间建立一个联系的话,我们可以认为,任何一个点都町以表示成一个从原点出发的矢量。为了明确点和向量的区别,在本书后面的内容中,我们将用于表示方向的矢量称为方向矢量。


向量

向量是具有大小(模) 和方向的有向线段;

向量没有位置,只有大小与方向;

向量是从尾指向箭头的,尾部是它的开端,箭头是它的终点;

向量的表示,几维就是()里有几个数字,如二维向量(2,4),三维向量(1,2,3);

向量通常用于表示相对于某个点的偏移;

我们通常用加粗的小写字母表示向量如a,b,c,d

标量

标量只有大小(模),没有方向;

我们通常使用普通的小写字母来表示标量如a,b,c,d



点是n维空间内的一个位置,无大小和方向;

点和向量虽然都是()表示,但几何意义完全不同;

零向量

零向量是唯一大小为零的向量

零向量是唯一一个没有方向的量

零向量不是一个点,因为没有定义某个位置

零向量便是没有位移,就像零标量表示的没有数量一样

向量与点

向量和点数学形式上相等,几何意义完全不同

点:有位置没有实际大小和方向

向量:无位置,有实际大小和方向

联系:任何一个点都可以看做是从原点出发的向量


向量的运算

在下面的内容里,我们将给出一些最常见的矢量运算。幸运的是,这些运算大多很好理解。对于每种运算,我们会先给出数学上的描述,然后再给出几何意义上的解释。

向量和标量的乘法/除法

还记得吗?标量是只有模没有方向的量,虽然我们不能把向量和标量进行相加/相减的运算(想象一下,你会把速度和距离相加吗),但可以对它们进行乘法运算,结果会得到一个不同长度且可能方向相反的新的向量。

公式非常简单,我们只需要把向量的每个分量和标量相乘即可:


类似的,一个矢量也可以被一个非零的标量除。这等同于和这个标量的倒数相乘:


下面给出一些例子:


注意,对于乘法来说,向量和标量的位置可以互换。但对于除法,只能是向量被标量除,而不能是标量被向量除,这是没有意义的。

从几何意义上看,把一个向量v和一个标量k相乘,意味着对向量v进行一个大小为|k|句的缩放。例如,如果想要把一个向量放大两倍,就可以乘以2。当k<0时,向量的方向也会取反。图4.17显示了这样的一些例子。

向量的加法和减法

我们可以对两个向量进行相加或相减,其结果是一个相同维度的新向量。

我们只需要把两个向量的对应分量进行相加或相减即可。公式如下:


下面是一些例子:

(1,2,3)+(4,5,6)=(5,7,9)

(5,2,7)-(3,8,4)=(2,-6,3)

需要注意的是,一个向量不可以和一个标量相加或相减,或者是和不同维度的向量进行运算。从几何意义上来看,对于加法,我们可以把向量a的头连接到向量b的尾,然后画一条从a的尾到b的头的向量,来得到a和b相加后的向量。也就是说,如果我们从一个起点开始进行了—个位置偏移a,然后又进行一个位置偏移b,那么就等同于进行了一个a+b的位置偏移。这被称为向量加法的三角形定则(triangle rule)向量的减法是类似的,如图4.18所示。


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

假设,空间内有两点a和b还记得吗,我们可以用向量a和b来表示它们相对于原点的位移。如果我们想要计算b相对于点a的位移,就可以通过把b和a相减得到,如图4.19所示

向量的模

正如我们之前讲到的一样,向量是有模和方向的。向量的模是一个标量,可以理解为是向量在空间中的长度。它的表示符号通常是在向量两旁分别加上一条垂直线(有的文献中会使用两条垂直线)。三维矢量的模的计算公式如下:

其他维度的矢量的模计算类似,都是对每个分量的平方相加后再开根号得到。下面给出一些例子:


其他维度的矢量的模计算类似,都是对每个分量的平方相加后再开根号得到。下面给出一些例子:


我们可以从几何意义来理解上述公式。对于二维向量来说,我们可以对任意向量构建一个三角形,如图4.20所示。


从图4.20可以看出,对于二维向量,其实就是使用了勾股定理,向量的两个分量的绝对值对应了三角形两个直角边的长度,而斜边的长度就是向量的模。

单位向量(标准化向量)

在很多情况下,我们只关心向量的方向而不是模。例如,在计算光照模型时,我们往往需要得到顶点的法线方向和光源方向,此时我们不关心这些向量有多长。在这些情况下,我们就需要计算单位向量(unit vector)。

单位向量指的是那些模为1的向量。单位向量也被称为被归一化的向量(normalized vector).,对任何给定的非零矢量,把它转换成单位向量的过程就被称为归一化(normalization)。

给定任意非零向量V,我们可以计算和v方向相同的单位向量。在本书中,我们通过在一个向量的头上添加一个戴帽符号来表示单位向量,例如为了对向量进行归一化,我们可以用向量的模除以该向量来得到,公式如下:


下面给出一些例子


零向量(即矢量的每个分量值都为0,如v=(0,0,0))是不可以被归一化的。这是因为做除法运算时分母不能为0。

从几何意义上看,对二维空间来说,我们可以画一个单位圆,那么单位向量就可以是从圆心出发、到圆边界的向量。在三维空间中,单位矢量就是从一个单位球的球心出发、到达球面的向量。图4.21给出了二维空间内的一些单位向量。

需要注意的是,在后面的章节中我们将会不断遇到法线方向(也被称为法向量)、光源方向等,这些向量不一定是归一化后的向量。由于我们的计算往往要求向量是单位向量,因此在使用前应先对这些向量进行归一化运算。


向量的点积

↑图片:【技术美术百人计划】图形 1.2.1 向量基础

向量之间也可以进行乘法,但是和标量之间的乘法有很大不同。向量的乘法有两种最常用的

种类:点积(dot product,也被称为内积,inner product)和叉积(cross product,也被称为外积,outer product)在本节中,

我们将讨论第一种类型:点积。

读者可能认为上面几节的内容都很简单,“这些都显而易见嘛”。那么从这一节开始,我们就会遇到一些真正需要花费力气(真的只要一点点)去记忆的公式。幸运的是,绝大多数公式是有几何意义的,也就是说,我们可以通过画图的方式来理解和帮助记忆。

比仅仅记住这些公式更加重要的是,我们要真正理解它们是做什么的。只有这样,我们才能在需要时想起来,“噢,这个需求我可以用这个公式来实现!”在我们编写Shader的过程中,通常程序接口都会提供这些公式的实现,因此我们往往不需要手工输入这些公式。例如,在Unity Shader中,我们可以直接使用形如dot(a,b)的代码来对两个向量值进行点积的运算。

点积的名称来源于这个运算的符号:a·b中间的这个圆点符号是不可以省略的。点积的公式有两种形式,我们先来看第一种。两个三维向量的点积是把两个向量对应分量相乘后再取和,最后的结果是一个标量。


下面是一些例子


向量的点积满足交换律,即a·b=b·a

点积的几何意义很重要,因为点积几乎应用到了图形学的各个方面。其中一个几何意义就是投影(projection)


↑图片:【技术美术百人计划】图形 1.2.1 向量基础



也就是说,点积的符号可以让我们知道两个向量的方向关系。

那么,如果 不是一个单位向量会如何呢?这很容易想到,任何两个向量的点积a·b等同于b在a方向上的投影值,再乘以a的长度。

点积具有一些很重要的性质,在Shader的计算中,我们会经常利用这些性质来帮助计算。

性质一:点积可结合标量乘法。

上面的“结合”是说,点积的操作数之一可以是另一个运算的结果,即向量和标量相乘的结果。公式如下:


也就是说,对点积中其中一个向量进行缩放的结果,相当于对最后的点积结果进行缩放。

性质二:点积可结合向量加法和减法,和性质一类似。

这里的“结合”指的是,点积的操作数可以是向量相加或相减后的结果。用公式表达就是


把上面的c换成-c就可以得到减法的版本。

性质三:一个向量和本身进行点积的结果,是该向量的模的平方。

这点可以很容易从公式验证得到:


这意味着,我们可以直接利用点积来求向量的模,而不需要使用模的计算公式。当然,我们需要对点积结果进行开平方的操作来得到真正的模。但很多情况下,我们只是想要比较两个向量的长度大小,因此可以直接使用点积的结果。毕竟,开平方的运算需要消耗一定性能。

现在是时候来看点积的另一种表示方法了。这种方法是从三角代数的角度出发的,这种表示方法更加具有几何意义,因为它可以明确地强调出两个向量之间的角度。

我们先直接给出第二个公式。

公式二:


向量的叉积

↑【技术美术百人计划】图形 1.2.1 向量基础

另一个重要的向量运算就是叉积(cross product),也被称为外积(outer product)o与点积不同的是,向量叉积的结果仍是一个向量,而非标量。

和点积类似,叉积的名称来源于它的符号:axb同样,这个叉号也是不可省略的。两个向量的叉积可以用如下公式计算:


上面的公式看起来很复杂,但其实是有一定规律的。图4.25给出了这样的规律图示。



需要注意的是,叉积不满足交换律,即axb≠bxa。实际上,叉积是满足反交换律的,即axb=-(bxa)而且叉积也不满足结合律,即(aXb) xc≠ax(bxc)。

从叉积的几何意义出发,我们可以更加深入地理解它的用处。对两个向量进行叉积的结果会得到一个同时垂直于这两个向量的新向量。我们已经知道,向量是由一个模和方向来定义的,那么这个新的矢量的模和方向是什么呢?

我们先来看它的模。axb的长度等于a和b的模的乘积再乘以它们之间夹角的正弦值。公式如下:


上述公式和点积的计算公式很类似,不同的是,这里使用的是正弦值。如果读者对中学数学还有记忆的话,可能还会发现,这和平行四边形的面积计算公式是一样的。如果你忘记了,没关系,我们在这里回忆一下。

如图4.26所示,我们使用a和b构建一个平行四边形。

我们知道,平行四边形的面积可以使用|b|/h来得到,即底乘以高。而又可以使用|a|和夹角 来得到,即


你可能会问,如果a和b平行(可以是方向完全相同,也可以是完全相反)怎么办,不就不能构建平行四边形了吗?我们可以认为构建出来的平行四边形面积为0,那么axb=0 注意,这里得到的是零向量,而不是标量0。

下面,我们来看结果向量的方向。你可能会说:“方向?不是己经说了方向了嘛,就是和两个矢量都垂直就可以了啊。”但是,如果你仔细想一下就会发现,实际上我们有两个方向可以选择,这两个方向都和这两个向量垂直。那么,我们要选择哪个方向呢?

这里就要和之前提到的左手坐标系和右手坐标系联系起来了,如图4.27所示。


这个结果是怎么得到的呢?来,举起你的双手!哦,不……先举起你的右手。在右手坐标系中,axb的方向将使用右手法则来判断。我们先想象把手心放在了 a和b的尾部交点处,然后张开你的手掌让手掌方向和a的方向重合,再弯曲你的四指让它们向b的方向靠拢,最后伸出你的大拇指!大拇指指向的方向就是右手坐标系中axb的方向了。如果你实在不明白怎么摆放和扭动你的手,那么就看图4.28好了。


同理,我们可以使用左手法则来判断左手坐标系中axb的方向。赶紧举起你的左手试试吧(你可能会发现这个姿势比较扭曲)!

需要注意的是,虽然看起来左右手坐标系的选择会影响叉积的结果,但这仅仅是“看起来”而己。从叉积的数学表达式可以发现,使用左手坐标系还是右手坐标系不会对计算结果产生任何影响,它影响的只是数字在三维空间中的视觉化表现而己。当从右手坐标系转换为左手坐标系时,所有点和向量的表达和计算方式都会保持不变,只是当呈现到屏幕上时,我们可能会发现,“咦,怎么图像反过来了!”。当我们想要两个坐标系达到同样的视觉效果时,可能就需要改变一些数学运算公式

复习总结:截图来源
B站【技术美术百人计划】图形 1.2.1 向量基础








相关阅读:

「技美之路 第01篇」图形 1.1 渲染流水线

文献地址:感谢作者无私分享
CSDN:古守音
https://blog.csdn.net/qq_43210334/article/details/114646000
参考《Shader入门精要》·冯乐乐女神著
B站视频 “技术美术百人计划”·霜狼_may
来源:Game艺视界
原文:https://mp.weixin.qq.com/s/UmuJO976HxvrzkOzpsqLjw