4. 学习Shader所需的数学基础
4.1 背景:描述一个物体的位置
4.2 笛卡尔坐标系
4.2.1 二维笛卡尔坐标系
· 原点
· x轴和y轴
· OpenGGL原点在屏幕右下角,往上y+,往右x+
· DX原点在左上角,往下y+,往右x+4.2.2 三维笛卡尔坐标系
· 多一个z轴
· 左手坐标系
· 右手坐标系4.2.3 左手坐标系和右手坐标系
· 将其中一个轴反向,就可以相互转化4.2.4 Unity使用的坐标系
· 对于观察空间,使用的是右手坐标系
· 以摄像机为原点,摄像机前进方向为z轴负方向
· z轴的减少意味着场景深度的增加
4.3 点和矢量
4.3.1 点和矢量的区别
· 点是n维空间中的一个位置,没有大小,宽度的概念
· 矢量是为了和标量区分开,矢量指n维空间中包含了模和方向的有向线段
· 通常,矢量用来表示相对于某个点的偏移4.3.2 矢量运算
· 矢量和标量的乘除法 (1,2)x 2 =(2,4)
· 矢量的加法和减法 (1,2)+(0,2)=(1,4)
· 矢量的模 (1,2)模为(1^2+2^2)开根号
· 单位矢量
转成单位矢量的过程是归一化
零矢量
· 矢量的点积 —— 投影 (x1,y1)·(x2,y2)=x1x2+y1y2 =|a||b|cosθ
· 矢量的叉积 —— 右手法则判断发现:模长为ab构成的四边形对角
二维:a x b = x1y2-x2y1
三维:a x b x c = y1z2-z1y2-x1z2+z1x2+x1y2-y1x2 (同高数)AxB=-(BxA) |AxB|=|a||b|sinθ
4.4 矩阵
- 4.4.1 矩阵定义:由一组数的全体,在括号内排列成m行n列的一个数表,并称它为mxn阵
- 4.4.2 和矢量联系起来:矢量可以看做列矩阵或者行矩阵
- 4.4.3 矩阵运算
· 矩阵和标量的乘法
· 矩阵和矩阵的乘法 - 4.4.4 特殊的矩阵
· 方块矩阵
· 单位矩阵
· 转置矩阵
· 逆矩阵
· 正交矩阵 - 4.4.5 行矩阵还是列矩阵
· Unity多把矢量转化为列矩阵来使用
4.5 矩阵的几何意义:变换
- 4.5.1 什么是变换
· 线性变换:保留矢量加和标量乘的变换
· 仿射变换:合并线性变换和平移变换的变换类型 - 4.5.2 齐次坐标
· 将三维矢量转换成四位变量
· 就可以表示三维的平移操作了 - 4.5.3 分解基础变换矩阵
· 分成四个部分
· 左上角表示旋转和缩放
· 右上角表示平移
· 左下角为0矩阵
· 右下角是标量1 - 4.5.4 平移矩阵
· 单位矩阵,右边一列为移动矩阵 - 4.5.5 缩放矩阵
· 先是单位矩阵,前三个为缩放系数值 - 4.5.6 旋转矩阵
· 绕轴旋转 - 4.5.7 复合变换
4.6 坐标空间
- 4.6.1 为什么要使用那么多不同的坐标空间
· 在顶点着色器流水线阶段,做的就是把模型顶点坐标从模型空间转换到齐次裁剪坐标空间
· 一些概念只在特定的坐标空间才有意义 - 4.6.2 坐标空间的变换
· 对坐标机进行平移变换
· 平移变换的变换矩阵的前3行和前3列,可以用来对法线方向、光照方向进行空间变换 - 4.6.3 顶点的坐标空间变换过程
· 一个顶点需要经过多个坐标空间才能最终被画在屏幕上,一个顶点最开始是在模型空间中定义的,最后它将会变换到屏幕空间中,得到真正的屏幕像素坐标
- 4.6.4 模型空间
· 模型空间(model space),是和某个模型或者说是对象有关的。有时模型空间也被称为对象空间(object space)或局部空间(local space)。每个模型都有自己独立的坐标空间,当它移动或旋转的时候,模型空间也会跟着它移动和旋转
· 在模型空间中,我们经常使用一些方向概念,例如”前(forward)””后(back)””左(left)””右(right)””上(up)””下(down)” - 4.6.5 世界空间
· 世界空间(world space)是一个特殊的坐标系,世界空间可以被用于描述绝对位置。在本书中,绝对位置指的就是在世界坐标系中的位置
· 在Unity中,世界空间同样使用了左手坐标系
· 但它的x轴、y轴、z轴是固定不变的。在Unity中,我们可以通过调整Transform组件中的Position属性来改变模型的位置,这里的位置指的是相对于这个Transform的父节点(parent)的模型坐标空间中的原点定义的,如果一个Transform没有任何父节点,那么这个位置就是在世界坐标系中的位置
· 我们可以想象成还有一个虚拟的模型,这个根模型的模型空间就是世界空间,所有的游戏对象都附属于这个根模型。同样,Transform中的Rotation和Scale也是同样的道理
· 顶点变换的第一步,就是将顶点坐标从模型空间变换到世界空间中。这个变换通常叫做模型变换(model transform) - 4.6.6 观察空间
· 观察空间(view space)也被称为摄像机空间(camera space)
· 观察空间和屏幕空间是不同的。观察空间是一个三维空间,而屏幕空间是一个二维空间。从观察空间到屏幕空间的转换需要经过一个操作,那就是投影(projection)
· 顶点变换的第二步,就是将顶点坐标从世界空间变换到观察空间中。这个变换通常叫做观察变换(view transform)
· 1. 一种方法是计算观察空间的三个坐标轴在世界空间下的表示,然后构建出从观察空间变换到世界空间的变换矩阵,再对该矩阵求逆来得到从世界空间变换到观察空间的变换矩阵
· 2. 另一种方法,即想象平移整个观察空间,让摄像机原点位于世界坐标的原点,坐标轴与世界空间中的坐标轴重合即可。这两种方法得到的变换矩阵都是一样的,不同的只是我们思考的方式 - 4.6.7 裁剪空间
· 顶点接下来要从观察空间转换到裁剪空间(clip space,也被称为齐次裁剪空间)中,这个用于变换的矩阵叫做裁剪矩阵(clip matrix),也被称为投影矩阵(projection matrix)
· 视锥体有两种类型,这涉及两种投影类型:
· 1. 一种是正交投影(orthographic):
· 1.1 在透视投影中,地板上的平行线并不会保持平行,离摄像机越近网格越大,反之相反
· 1.2 可以注意到,透视投影模拟了人眼看世界的方式
· 1.3 因此,在追求真实感的3D游戏中我们往往会同透视投影
· 2.一种是透视投影(perspective projection)
· 2.1 而在正交投影中,所有的网格大小都一样,而且平行线会一直保持平行
· 2.2 而正交投影则完全保留了物体的距离和角度
· 2.3 而在一些2D游戏或渲染小地图等其他HUD元素时,我们会使用正交投影
- 透视投影
· 在视锥体的6块裁剪平面中,有2块比较特殊,分别为近裁剪平面(near clip plane)和远裁剪平面(far clip plane)—— 通过一个投影矩阵把顶点转换到一个裁剪空间中 —— 首先是为投影做准备、齐次是对x、y、z分量进行缩放
· 我们可以通过Camera组件的Field of View(简称FOV)属性来改变视锥体竖直方向的张开角度,而Clipping Planes中的Near和Far参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的远近
· 在Unity中,一个摄像机的横纵比由Game视图的横纵比和Viewport Rect中的W和H属性共同决定
· 根据已知的Near、Far、FOV、和Aspect的值来确定透视投影的投影矩阵 - 正交矩阵
· 首先看一下正交投影中的6个裁剪平面是如何定义的
· 正交投影的视锥体是一个长方体
· 可以通过Camera组件的Size属性来改变视锥体竖直方向上高度的一半,而Clipping Planes中的Near和Far参数可以控制视锥体的近裁剪平面和远裁剪平面距离摄像机的近
· 我们可以通过摄像机的横纵比得到横向信息Aspect
- 4.6.8 屏幕空间
·
屏幕空间是一个二维空间,因此我们必须把顶点从裁剪空间投影到屏幕空间中,来生成对应的2D坐标
·
首先,我们需要进行标准齐次除法(homogeneous division),也被称为透视除法(perspective division) —— 经过齐次除法后,透视投影和正交投影的视锥体都变换到一个相同的立方体内。在Unity中,从裁剪空间到屏幕空间的转换是由底层帮我们完成的。我们的顶点着色器只需要把顶点转换到裁剪空间即可
· 根据变换后的x和y坐标来映射输出窗口的对应像素坐标 - 4.6.9 总结
· 只有在观察空间中Unity使用了右手坐标系
4.7 法线变换
- 法线(normal),也被称为法矢量(normal vector)
- 切线(tangent),也被称为切矢量(tangent vector)