unityUI多个相似_笔记

本系列为作者学习UnityShader入门精要而作的笔记,内容将包括:

  • 书本中句子照抄 + 个人批注
  • 项目源码
  • 一堆新手会犯的错误
  • 潜在的太监断更,有始无终

总之适用于同样开始学习Shader的同学们进行有取舍的参考。


文章目录

  • 复习
  • 知识点复习
  • 左右手坐标系
  • Unity中的坐标系
  • 上章节练习题答案
  • 点和向量
  • 定义
  • 点和向量的区别
  • 去看线性代数的本质!
  • 向量运算
  • 向量加减
  • 向量乘除
  • 向量模长
  • 归一化
  • 向量的点积
  • 向量叉乘
  • 练习题


(该系列笔记中大多数都会复习前文的知识,特别是前文知识非常重要的时候,这是为了巩固记忆,诸位可以直接通过目录跳转)

复习

知识点复习

上节我们学习了笛卡尔坐标系(正交坐标系)。笛卡尔坐标系中包含了以下要素:

  • 原点,它是整个坐标系的中心,我们以0坐标代表该点
  • n维笛卡尔坐标系中的n个轴都是两两正交的,例如三维笛卡尔坐标系中xy,xz,yz都互相垂直。

我们以每条轴箭头指向的方向为正方向,反向为负方向。以正方向上的单位长度称为基向量( 或者基底 ,或者标准正交基)。

(在三维软件中,我们喜欢以红色直线代表x轴,绿色直线代表y轴,蓝色直线代表z轴)

左右手坐标系

unityUI多个相似_线性代数_02

在三维坐标系中,有两种不同的坐标系——左手坐标系和右手坐标系,判断坐标系是哪种的方法就是如上图所示,伸出左手(右手),大拇指指向x轴正方向,食指指向y轴正方向,中指指向z轴正方向,如果其中任意两轴方向对齐,而另一条轴方向相反,证明不是当前手的坐标系。

如果两个坐标系都是左手(右手)坐标系的话,那么这两个坐标系经过一系列旋转一定是可以重合的,这种性质被我们称为旋向性 。

unityUI多个相似_笔记_03

在左手坐标系中,判断旋转正方向的方法是左手法则(右手坐标系中则是右手法则)。判断方法是,手虚握坐标轴,大拇指指向正方向,四指弯曲方向就是旋转正方向。

我们之所以要引入坐标系,其根本目的就是为了在空间中描述某个点的位置。而在Unity等等三维软件中,我们固定了一个唯一的初始坐标,才能够统一的描述这个三维软件的空间内的所有物体。

Unity中的坐标系

Unity中,对于模型空间和世界空间,Unity使用的是左手坐标系。

unityUI多个相似_笔记_04

而对于观察空间来说,Unity使用的是右手坐标系。简单来说就是以摄像机为原点的坐标系,再这个坐标系中,摄像机的镜头方向是z轴的负方向(也就是z轴的正方向实际上是从屏幕指向屏幕前的你),这与模型空间和世界空间中的定义相反,z轴的减少意味着场景深度的增加。

上章节练习题答案

  1. 伸出左手,大拇指指向右方,食指指向前方,发现中指指向下方,和题中坐标系不重合,证明该坐标系是右手坐标系。
  2. 如下图所示: 左边是一个左手坐标系,右边是一个右手坐标系,我们先找到对应的(0,0,1)点,然后按题目要求绕y轴旋转。其中左手坐标系的旋转方向用左手法则发现正方向是绕y轴顺时针,右手坐标系的旋转方向则用右手法则发现正方向是绕y轴逆时针。因此进行相应旋转,旋转90°后点落在x轴上。二者答案都为(1,0,0)。

在上图中画出的两个坐标系,虽然点的坐标是相同的,但如果将两坐标系原点重合(置于同一空间下),并用左手坐标系来统一描述两点的坐标(忽略右手坐标系的z轴)。那么点1坐标为(1,0,0),点2坐标则为(-1,0,0),如下图4.51所示:

unityUI多个相似_学习_05

unityUI多个相似_笔记_06

(上图4.50虽然两点重合在了同一坐标,但两个坐标系并不在同一空间,因为z轴的正方向不一致)

  1. 如图所示: 小球相对于摄像机的深度值为10,而根据视锥方向可知,小球目前在摄像机的镜头前向,而该方向实际上是观察空间的z轴的反方向(从屏幕到屏幕前的人的方向为正方向),因此小球在观察空间的坐标应为(0,1,-10),z值为-10。 而在以摄像机为坐标建立的模型空间下,由于模型空间是左手坐标系,因此用左手对准上图中的x,y轴,发现两个坐标系重合(当然了,因为unity中的坐标系就是左手坐标系嘛),因此确定小球在摄像机的模型空间下的坐标为(0,0,10),因此z值为10。

点和向量

定义

点(point) 是n维空间中的一个位置,它没有大小,宽度这些概念。一个空间是由无数的点构成的,我们可以用任意点的坐标描述物体在该空间中的位置。在二维,三维笛卡尔坐标系中,我们用实数来表示点的坐标,例如unityUI多个相似_标量_07unityUI多个相似_笔记_08

向量(vector,或者矢量,但我建议还是叫做向量)。几何定义上讲,向量是n维空间中包含了模长(magnitude) 和方向(direction) 的有向线段 。向量与标量(scalar) 要作区分:标量只有模长,没有方向。

对于向量的表示,我们可以使用unityUI多个相似_unityUI多个相似_09来表示【实际上我更喜欢用数学的方式unityUI多个相似_线性代数_10来表示,用箭头更能表示它是有方向的】

其中,a,b代表了其在对应的轴方向上的长度(以坐标系的基向量为单位长度)。

与书中有所不同,接下来我会用小写字母unityUI多个相似_unityUI多个相似_11表示标量

用带箭头的字母unityUI多个相似_unityUI多个相似_12 表示向量

用大写字母unityUI多个相似_线性代数_13等表示矩阵

unityUI多个相似_unityUI多个相似_14

如上图所示,一个向量通常由一个箭头表示,我们以箭头方向称为向量的头,另一端称为向量的尾。在坐标系(线性代数)中,以原点为尾,指向的坐标点为头。

(注意,此处我不建议大家看书中原作者对向量的解释,原作者的解释大多是从物理角度出发,但是学习线性代数,我们需要从数学的视角,从数字上和几何上理解向量,因此我依然推荐大家去看b3b1的线性代数的本质 - 01 - 向量究竟是什么?)

原作者说向量可以表示相对于某个点的偏移,因此可以在空间中移动。但是线性代数中不要随便移动一个向量,向量一定以原点为尾,指向的坐标点为头。因为unityUI多个相似_线性代数_10向量是以原点为起点,坐标系的基底为单位长度来描述该向量相对于原点的偏移,因此我们不能随意改变它在坐标系中的位置。

unityUI多个相似_笔记_16

只有在进行向量计算的时候,我们才允许向量移动,将一个向量的头部或尾部对齐到其他向量的头部上。但是最终结果得到的向量,依然是原点为尾,指向的坐标点为头的向量


点和向量的区别

unityUI多个相似_线性代数_17

还是看上图,如果我们把点和向量放在同一个坐标系下,我们会发现二者虽然数学上的表示方式一样,但是在空间上,向量是从原点出发,指向目标点的。也就是说任何一个点都可以由一个向量表示。

那么点和向量区别在哪呢?虽然二者都可以用(x,y)来表示,但是注意,向量之所以用这种方式来表示,是因为我们默认它的尾部为原点。实际上应该是(x-0,y-0)。向量的表示实际是两个点之间坐标的差值(顶部点减去尾部点)。

如果我们用矩阵的方式来表示向量:例如unityUI多个相似_笔记_18。那么实际上表示的是unityUI多个相似_标量_19unityUI多个相似_unityUI多个相似_20就是当前向量的基向量,对应在这个笛卡尔坐标系下就是x正向上的单位长度,和y正向上的单位长度。

那么如果我们任意改变x和y的值?这样的话,其实意味着对基向量的任意拉伸组合,最终我们可以得到的向量将遍布整个二维空间,我们将其称为基向量所组成的张成空间(span space) 。

unityUI多个相似_标量_21

如果用向量来遍布整个空间,实在太过拥挤,最终我们会用向量的终点来表示这个向量,因此,向量就表示为了点。


去看线性代数的本质!

好吧,看书中的这些文字其实不如去复习一遍线性代数的本质,接下来部分参考价值不大的内容我就省略过了。


向量运算

向量加减

unityUI多个相似_线性代数_22

unityUI多个相似_标量_23

假设有向量a和向量b,则:unityUI多个相似_标量_24

几何上看,向量相加减,则可以用向量计算的三角形法则得出结果向量。矩阵上来看,以左图向量相加为例,我们将b向量移动到对应原点位置成unityUI多个相似_线性代数_25。然后将unityUI多个相似_学习_26在xy轴上的分量进行相加,发现最终结果和三角形法则画出的是一模一样的。

向量乘除

unityUI多个相似_线性代数_27

我们可以用一个标量来对向量进行乘除:

unityUI多个相似_学习_28

还记得标量的英文吗?Scaler ,我认为很形象,如果在几何上看,其实最终结果就是对一个向量进行缩放(拉伸),缩放的英文不就是Scale吗。(上图对于向量的拉伸不太准确,应当保持起点不变,终点拉伸到对应坐标)

向量模长

模长公式:unityUI多个相似_标量_29

简单的计算,因为几何上直观来看就是运用了勾股定理。

归一化

想起学习线代时的痛点之一施密特正交化,根据线性无关的向量组构造一个标准正交化向量组。反正怎么正交化已经忘了,但是如何归一化还是记得的。

给定任意非零向量unityUI多个相似_线性代数_30,将其归一化为模长为1的单位向量,归一化公式为:unityUI多个相似_标量_31

unityUI多个相似_学习_32

归一化的单位向量模长为1,因此所有归一化向量可以构成一个单位圆。其落点都在单位圆的圆周上。

在后文章节中,我们将会不断遇到法线方向,光源方向这些概念。由于我们的计算要求往往需要对应的向量是单位向量,因此使用前应当将向量先归一化。

向量的点积

向量的点积公式如下:unityUI多个相似_unityUI多个相似_33

点积满足交换律,即:unityUI多个相似_标量_34

unityUI多个相似_unityUI多个相似_35

点积其实本质上计算的是投影与向量的乘积。对于unityUI多个相似_线性代数_36而言,其计算结果实质上是 unityUI多个相似_标量_37的投影长度 乘以 unityUI多个相似_学习_38

unityUI多个相似_笔记_39

什么是投影?假设有一道光源垂直于向量a所在的直线,那么b在a方向上的影子,就是b向量首尾两点作垂直,最后在a方向直线上的连线,这个线段被我们称之为投影。

unityUI多个相似_unityUI多个相似_40

根据两个向量之间的夹角,点积的符号也不同,若夹角小于90°则结果>0,若等于90°则=0,若大于90°则<0

(推荐视频:07点积与对偶性,解释了为什么点积的公式在几何上的表现是这样的。简单来说,unityUI多个相似_标量_41实质上与矩阵乘法unityUI多个相似_线性代数_42相等,而后者计算结果实际上是将二维矩阵w应用线性变换v使其降维到了一维空间,这个一维空间就是我们用于投影的数轴,降维后的结果就是投影,所以向量点积本质上就是一个将矩阵从二维变换到一维的线性变换。)

unityUI多个相似_线性代数_43

从三角函数上看,点积公式还可以表示为下列形式:unityUI多个相似_标量_44 (其实还是投影乘以模长,投影是unityUI多个相似_unityUI多个相似_45,模长是unityUI多个相似_标量_46)

投影还有一些其他的性质:unityUI多个相似_线性代数_47unityUI多个相似_标量_48unityUI多个相似_线性代数_49


向量叉乘

另一个重要的运算是向量的叉乘(cross product) ,也称为外积(outer product) 。

叉乘的公式是:

unityUI多个相似_学习_50

看起来好复杂好难记,为什么是这样的?

如果用线性代数来表示的话就清晰了:

unityUI多个相似_标量_51

纠正一下上式子,虽然结果正确,但是没写对unityUI多个相似_线性代数_52的计算。记该矩阵为X

unityUI多个相似_学习_53

实际上叉乘就是加上一列基向量构成一个新矩阵,并计算该矩阵的行列式。

(为什么要这样,别问我,以线性代数的眼光看叉乘)

unityUI多个相似_学习_54

记住一个简单的结论就是,两个向量叉乘,最终会得到一个新向量,这个新向量的长度是unityUI多个相似_学习_55向量构成的平行四边形的面积,而新向量的方向,由原坐标系指定,且垂直于这个平行四边形。如果你使用右手坐标系,就举起右手,反之使用左手,使得任意两根手指与unityUI多个相似_学习_55对齐,剩下那根的方向就是新向量的方向。

unityUI多个相似_线性代数_57

这个叉乘出来的向量的模长由于和平行四边形面积一致,所以我们也可以得到叉乘向量的模长公式:unityUI多个相似_线性代数_58

叉乘是无法交换的,unityUI多个相似_笔记_59

从几何意义上去理解点乘和叉乘,就会发现其中奥妙所在,为什么点乘可以交换,而叉乘无法交换:

因为点乘实质上是二维降维成一维,无论二维一维,它们都满足我们之前说的旋向性(handedness),因此可以交换。

而叉乘的三个向量建立了一个非正交的左右手三维坐标系(由原坐标系为左手还是右手指定),如果交换叉乘顺序,则产生的新向量的方向是相反的,就变成了另一只手对应的坐标系,所以结果需要加个负号。

叉乘也不满足结合律:unityUI多个相似_unityUI多个相似_60

叉乘最常见的应用就是计算垂直于一个平面、三角形的向量,还可以用于判断三角面片的朝向。


练习题

  1. 判断题 (1)一个向量的大小不重要,只需要在正确的位置把它画出来即可 (2)点可以被认为是位置向量,这是通过把向量的尾部固定在原点得到的 (3)选择左手坐标系还是右手坐标系很重要,这会影响到叉乘的计算

2.计算题: (1)unityUI多个相似_学习_61 (2)unityUI多个相似_标量_62 (3)unityUI多个相似_笔记_63 (4)unityUI多个相似_unityUI多个相似_64 (5)unityUI多个相似_线性代数_65 (6)unityUI多个相似_笔记_66 (7)unityUI多个相似_笔记_67

3.假设场景中有一光源位于unityUI多个相似_标量_68处,还有一个点位于unityUI多个相似_unityUI多个相似_69,请问光源到点的距离是?

4.计算下列运算: (1)unityUI多个相似_笔记_70 (2)unityUI多个相似_学习_71 (3)unityUI多个相似_标量_72 (4)unityUI多个相似_unityUI多个相似_73 (5)unityUI多个相似_标量_74

5.已知向量a和向量b,a的模长为4,b的模长为6,它们间的夹角为60°,求计算: (unityUI多个相似_标量_75 (1) unityUI多个相似_标量_76 (2) unityUI多个相似_笔记_77

6.假设,场景中有一个NPC,它位于点unityUI多个相似_标量_78处,它的前方用向量unityUI多个相似_unityUI多个相似_79表示。 (1)假设现在玩家移动到了点unityUI多个相似_笔记_80处,那么如何判断玩家在NPC的前方还是后方?使用上述学习的知识来描述。 (2)使用(1)中的描述方法,代入点unityUI多个相似_笔记_81来验证答案 (3)现在,NPC只能观察到有限的视角范围,其视角角度为unityUI多个相似_线性代数_82,也就是视野在前方左侧unityUI多个相似_笔记_83到前方右侧unityUI多个相似_笔记_83。那么我们如何通过点积来判断NPC是否可以看到点unityUI多个相似_笔记_80? (4)在(3)的基础上,我们又要求NPC只能看见固定距离内的对象,如何判断?

7.在渲染中我们时常会需要判断一个三角面片是正面还是背面,这可以通过判断三角形的3个顶点在当前空间中是顺时针还是逆时针排序来得到。给定三角形的三个顶点unityUI多个相似_unityUI多个相似_86unityUI多个相似_学习_87unityUI多个相似_标量_88,假设我们使用的是左手坐标系,且unityUI多个相似_unityUI多个相似_86unityUI多个相似_学习_87unityUI多个相似_标量_88都位于xy平面上(即它们的z分量都为0),且人眼位于z轴的负方向上,向z轴正方形观察,如图所示:

unityUI多个相似_unityUI多个相似_92

请问如何判断这三个顶点的顺序是顺时针还是逆时针?