Shader预备知识二-------所需的数学基础

Shader预备知识二-------所需的数学基础

数学基础,哦,我没有数学基础,那没事了
-----------博主:mx

坐标系:三位笛卡尔坐标系的三个坐标轴相互垂直且长度为1,成为标准正交基。对于相互垂直,但是长度不为一的基向量称为正交基

两种不同的坐标系:左手坐标系和右手坐标系。这两个坐标系具有不同的旋向性,无法通过旋转的方法来让他们的坐标轴指向重合

(注意:unity中模型空间和世界空间使用的是左手坐标系,观察空间使用的是右手坐标系)

 

矢量(向量):包含了模(长度)和方向的有向线段

 

矢量运算:

  1. 标量乘除:(矢量对应分量乘除标量)
    • 乘:kV=(kVx,kVy, kVz)
    • 除:

 

(2)矢量加减:(矢量对应分量加减另一个矢量对应的分量)

 

加法遵循三角形法则 / 平行四边形法则

 

矢量的模:分量平方和开根

  

 unity里的方法:Vector3.normalized 归一化

单位矢量:模为1的矢量。一个矢量转化为单位矢量的过程称为归一化。

  归一化方法:矢量除以它的模

 

(零矢量:每个分量均为零,不能被归一化)

矢量点积:几何意义是一个矢量在另一个矢量上的投影

公式一:

 

公式二:

 

在Unity中,点积表示为Vector3.Dot(Vector3,Vector3):float——参数为2个向量,返回值为浮点型。

 

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

性质二:点积可以结合矢量加法和减法

性质三:点积满足交换律

性质四:一个矢量与自身进行点积运算的结果为模平方

 

矢量叉积:几何意义求出来的是一个垂直于原本两个矢量的矢量,其模可以表示原本两个矢量组成的平行四边形的面积

公式:

(模)公式:

在Unity中,叉积表示为Vector3.Cross(Vector3,Vector3):Vector3——参数为2个向量,返回值也为向量。  

方向:a X b 的方向可以用右手法则来判断

 

注意:叉积不满足交换律和结合律

 

矩阵和矢量的联系:矢量可以看成是n X 1的列矩阵或者1 X n的行矩阵,其中n对应了矢量的维度

 

矢量运算:

矩阵和标量的乘法:矩阵的每个元素和该标量相乘

矩阵和矩阵的乘法:第一个矩阵的第n行的对应元素与第二个矩阵的第m列对应  

(可以相乘必须满足第一个矩阵的列数与第二个矩阵的行数相等)

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

性质二:矩阵乘法满足结合率

-----------博主:mx

特殊的矩阵:

方块矩阵(方阵):行数与列数相等的矩阵

对角矩阵(特殊的方阵):除了对角元素外其他元素均为0的矩阵

单位矩阵(特殊的对角矩阵):对角元素均为1的对角矩阵。注意:任何矩阵和他相乘均是原来的矩阵

 

转置矩阵:原矩阵的第i行转变成第j列,而第j列转变成第i行得到的矩阵。数学公式:

性质一:矩阵转置的转置等于原矩阵

性质二:矩阵串接的转置等于反向串接各个矩阵的转置。公式:

 

逆矩阵:逆矩阵于原矩阵相乘得到的就是一个单位矩阵:

c++数学库Eigen可以直接求得

性质一:逆矩阵的逆矩阵是原矩阵本身

性质二:单位矩阵的逆矩阵是它本身

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

性质四:矩阵串接相乘之后的逆矩阵等于反向串接各个矩阵的逆矩阵

 

正交矩阵:如果一个方阵和他的转置矩阵的乘积是单位矩阵的话,则这个矩阵是正交矩阵。

 可以易知正交矩阵的逆矩阵和转置矩阵相等

3 X 3的正交矩阵的特点:

(1)矩阵的每一行,即c1、 c2和c3是单位矢量,因为只有这样它们与自己的点积才能是1

(2)矩阵的每一行,即c1, c2和c3之间互相垂直,因为只有这样它们之间的点积才能是0

(3)上述两条结论对矩阵的每一列同样适用,因为如果M是正交矩阵的话, M的转置也会是正交矩阵。

 

注意:在unity中常规做法是把矢量放在矩阵右侧,即把矢量转换成列矩阵来进行运算

 

 

矩阵的几何意义:变换

线性变换:缩放、旋转、错切、镜像(正切投影)

平移变换:平移

仿射变换:合并了下您变换和平移变换的变换类型。仿射变换可以用一个4X4的矩阵来表示。我们需要把矢量拓展到一个四维空间中,这就是齐次坐标空间。

 

平移矩阵:

 

其逆矩阵:

特点:平移不会对方向矢量产生任何影响

 

缩放矩阵:

如果缩放系数Kx=Ky=Kz,这样的缩放称为统一缩放,否则称为非统一缩放

 

旋转矩阵:

绕X轴旋转θ度:

 

绕Y轴旋转θ度:

 

绕Z轴旋转θ度:

 

 

复合变换:把平移、旋转、缩放结合起来,形成一个复杂的变化过程

绝大多数情况下,我们约定变化的顺序是先缩放、再旋转、最后平移。如果把缩放放后面,有可能造成坐标的变化造成不必要的错误

在unity中旋转的顺序是zxy,并且不是叠加旋转,是依据初值旋转

 

 

坐标空间的变换

子坐标空间转换到父坐标空间

  1. 从坐标空间开始
  2. 向x轴方向移动a个单位
  3. 向y轴方向移动b个单位
  4. 向z轴方向移动c个单位

 

 

顶点的坐标空间转换过程

 

模型空间----世界空间---观察空间---齐次裁剪空间----屏幕空间

 

第一步:顶点坐标从模型空间转换到世界空间,这个变换叫模型变换

 

第二步:顶点坐标从世界空间转换到观察空间,这个变换叫观察变换

Unity观察空间使用的是右手坐标系,+x轴指向右方,+y指向正上方,+z轴指向摄像机后方。

计算观察空间的三个坐标轴在世界空间下的表示 方法:

方法一:构建出从观察空间变换到世界空间的变换矩阵,再对该矩阵求逆来得到从世界空间变换到观察空间的变换矩阵

方法二:想象平移整个观察空间,让摄摄像机的原点位于世界坐标的原点,坐标轴与世界空间中的坐标轴重合即可

 

第三步:顶点坐标从观察空间转换到裁剪空间,这个过程叫投影变换

裁剪空间的目标是能够方便地对渲染图元进行裁剪,完全位于这块空间内部的图元将会被保留,完全位于这块空间外部的图元将会被剔除,而与这块空间边界相交的图元就会被裁剪。这块空间由视锥体来决定

 

视锥体有两种类型:正交投影和透视投影

(透视投影模拟了人眼看世界的方式,而正交投影则完全保留了物体的距离和角度。)

在视锥体的6块裁剪平面中,有两块裁剪平面比较特殊,他们分别是近裁剪平面和远裁剪平面

使用投影矩阵来使得更加方便、通用、整洁的方式来进行裁剪工作。投影矩阵的两个目的:

  1. 为投影做准备。,虽然投影矩阵的名称包含了投影二字,但是它并没有进行真正的投影工作,而是在为投影做准备。真正的投影发生在后面的齐次除法过程中。而经过投影矩阵的变换后,顶点的w分量将会具有特殊的意义。

  2. 对x、y、z分量进行缩放。经过投影矩阵的缩放之后,我们可以使用w分量作为一个范围值,如果x、y、z分量均位于这个范围内,就说明该顶点位于裁剪空间中

 

透视投影:

 

属性:FOV是Camera组件中的Field of View ,它可以改变视锥体垂直方向的张开角度;Near和Far可以拿来表示视锥体的近裁剪平面和远裁剪平面距离摄像机的远近;Aspect表示当前摄像机的中纵横比

Aspect计算方法:

 

 

-----------博主:mx

正交投影:

 

Aspect计算方法:

 

 

(注意:裁剪矩阵会改变控件的旋向性,空间从右手坐标系转换到了左手坐标系。这意味着,离摄像机越远,z值越大)

如果一个顶点在视锥体内,那么它变换后的坐标必须满足:

而不满足条件的图元需要被剔除或者裁剪

 

第四步:顶点坐标从裁剪空间转换到屏幕空间,这个过程叫屏幕映射

屏幕空间是一个二维空间,因此必须把顶点从裁剪空间投影到屏幕空间,来生成对应的2D坐标,该过程有两个步骤:

1.齐次除法(透视除法):齐次坐标系的x、y、z分量除以w分量。在OpenGL中这一步称作归一化的设备坐标。

(注意在DirectX中z的分量范围会是[0,1],但是在OpenGL中x、y、z分量的范围是[-1,1]。而unity选用了OpenGL的齐次裁剪空间)

2.屏幕映射:经过齐次触发后,透视投影和齐次投影的视锥体都会变换到一个相同的立方体。现在需要根据变换后的x和y坐标来映射输出窗口的像素坐标。

 

齐次除法和屏幕映射的过程可以用下面的公式来总结:

 

总结:

顶点着色器的最基本任务是把顶点坐标从模型空间转换到裁剪空间,对应前三个顶点变换过程。而在片元着色器中,可以得到该片元在屏幕空间的像素位置。

 

 

 

法线变换:在变换模型的时候不仅需要变换顶点,还需要变换发现,以便在后续处理(如片元着色器)中计算光照等

切线变换:由于切线是两个顶点之间的差值计算得到的,我们可以直接使用用于变换顶点的变换矩阵来变换切线。假设变换公式为:

 

法线变换:使用一个矩阵G来变换法线NA,使得变换后的法线仍然与切线垂直。根据法线切线相互垂直,可以推出,即是原变换矩阵的逆转置矩阵来变换法线就可以得到正确的结果。

(注意:如果变换矩阵是正交矩阵,那么逆转置矩阵为它本身。如果变换只包括旋转变换,那么这个变换矩阵就是正交矩阵。如果变换只包含旋转和统一缩放,而不包含非统一缩放,我们可以利用统一缩放系数K来得到变换矩阵的逆转置矩阵

 

UnityShader的内置变量(数学篇)

 

 

 

 

注意:

在CG中,对float4X4等类型的变量是按行优先的方式进行填充的

Unity中提供的矩阵类型Matrix4X4则是使用按列优先的方式

 

在顶点/片元着色器中,有两种方式来获得片元的屏幕坐标

一种是在片元着色器的输入中声明VPOS或者WPOS语义(VPOS是HLSL中对屏幕坐标的语义,而WPOS是CG中对屏幕坐标的语义)

(如何得到视口空间:把屏幕空间除以屏幕分辨率来得到视口空间,左下角就是(0,0)右上角就是(1,1))

 

另一种是通过unity提供的ComputeScreenPos函数。这个函数在UnityCG.cginc里被定义。通常用法需要两个步骤,首先在顶点着色器中将ComputeScreenPos的结果保存在输出结构体中,然后再片元着色器中进行一个齐次除法运算首得到视口空间下的坐标

(注意:ComputeScreenPos并不会直接得到视口空间中的位置,我们需要再片元着色器中除以它的w分量来得到真正的视口空间中的坐标)

 

-----------博主:mx

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值