Unity Shader数学基础
本篇介绍的是坐标系及不同坐标系间通过矩阵进行转换
坐标系和旋转正向
左手坐标系和右手坐标系
Unity使用左手系,但是对于观察空间来说,Unity使用的是右手坐标系,摄像机的前向是z轴的负方向
矩阵
转置矩阵性质:
转置矩阵的转置等于原矩阵
矩阵串接的转置等于反向串接各个矩阵的转置
逆矩阵性质:
原矩阵乘转置矩阵为单位矩阵
逆矩阵的逆矩阵是原矩阵
单位矩阵的逆矩阵是本身
转置矩阵的逆矩阵是逆矩阵的转置
判断可逆:矩阵的行列式不为0
正交矩阵性质:
矩阵的每一行都是单位矢量
矩阵的每一行相互垂直
对列一样适用
正交:矩阵乘转置矩阵是单位矩阵 也就是转置矩阵等于逆矩阵
一个正交矩阵的行和列之间分别构成了一组标准正交基,但如果使用一组正交基来构建一个矩阵的话,这个矩阵就不一定是正交矩阵
矩阵变换
包括平移,缩放,旋转等基础变换
复合变换,约定变换顺序:先缩放,再旋转,后平移
坐标系变换
假设两个坐标空间A,B
从A空间变换到B空间的矩阵:就是A空间的X,Y,Z轴在父空间下的矢量表示 按列
B空间到A空间 就是按行
顶点的坐标空间变换过程
模型空间
每个物体自身的局部空间,Unity在模型空间是左手系,模型的顶点都是相对于模型空间的原点定义的
世界空间
观察空间
摄像机的本地空间,遵循右手系,符号OpenGL传统,摄像机的正前方指向的是-z轴方向。
观察空间是三维空间,屏幕空间是二维空间,通过投影变换进行转换
为了得到顶点在观察空间的位置,两种方法:
计算观察空间3个坐标轴在世界空间下的表示,然后构建从观察空间变换到世界空间的变换矩阵,再对该矩阵进行求逆。
想象摄像机是从世界原点经过怎样的变换变换到现在的位置,然后用逆变换变换回去。
裁剪空间
顶点接下来要从观察空间变换到裁剪空间,用于变换的矩阵为裁剪矩阵,也叫做投影矩阵
裁剪空间的目标是能够方便地对渲染图元进行裁剪,根据视锥体(view frustum)来决定裁剪范围。
视锥体由六个平面包围而成,是空间中的一块区域,决定了摄像机可以看到的空间。
其中有两种特殊的裁剪平面:近裁剪平面(near clip plane)和远裁剪平面(far clip plane)。
它们决定了摄像机可以看到的深度范围。
投影矩阵有两个目的:
为投影做准备:真正的投影发生在后面的齐次除法中。经过投影变换后,顶点的w分量具有特殊的意义
对x,y,z分量进行缩放。经过投影矩阵的缩放后,可以直接使用w分量作为一个范围值,如果x,y,z分类都位于这个范围内,就说明顶点位于裁剪空间内。
unity(shader入门精要)投影变换原理推导(保姆级)
透视投影
通过Camera的Field of View(FOV)和Near,Far,Aspect(射线机的纵横比)决定
得到的投影矩阵如下:
这里的投影矩阵针对的是观察空间为右手坐标系,使用列矩阵在矩阵右侧相乘,且变换后z分量的范围在【-w,w】之间的情况。
本质上就是对x,y,z分量进行了不同程度的缩放,z分量进行了一个平移
正交投影
使用正交投影的投影矩阵对顶点进行变换后,w分量仍然为1。
本质是因为投影矩阵最后一行的不同,透视投影的投影矩阵的最后一行是 【0 0 -1 0】,正交投影的投影矩阵的最后一行是【0 0 0 1】
屏幕空间
经过投影矩阵变换后可以进行裁剪操作,裁剪后,需要进行真正的投影——把视锥体投影到屏幕空间=>得到真正的像素位置
齐次除法(透视除法)
x,y,z都除w=>归一化的设备坐标NDC
齐次除法后的立方体的x,y,z分量的范围都是【-1,1】
DirectX中是【0,1】
坐标映射
根据变换后的x,y坐标来映射窗口的像素坐标。
整体就是把【-1,-1】【0,0】分别映射到【0,0】【SCREENWIDTH,SCREENHEIGHT】
z(clipz/clipw)分量通常会被用于深度缓冲。
clipw作用:
齐次除法的分母
透视校正插值
视口空间
将【-1,1】的NDC映射到【0,1】的视口空间下
总结
法线变换
使用顶点变换矩阵变换法线带来的问题:
Unity Shader内置变量
内置的用于空间变换和摄像机以及屏幕参数的内置变量。可以在UnityShaderVariable.cginc文件中找到定义和说明。
Unity内置的变换矩阵
Unity_MATRIX_T_MV:如果MV是正交矩阵=>逆矩阵=转置矩阵=>MV矩阵的逆矩阵,将顶点和方向矢量从观察空间转换到模型空间
什么时候正交?
只包含旋转
只包含旋转和缩放 缩放系数为k,则对应逆矩阵要乘以1/k
只对方向矢量进行变换,忽略平移影响,只使用前三行和前3列来变换
摄像机和屏幕参数
Unity提供的访问当前正在渲染的摄像机的参数信息的内置变量:
CG语言中变量的一些注意点
通常右乘向量按照列矩阵进行乘法,Unity内置矩阵也都是按列存储的
CG矩阵初始化是按照行优先的顺序填充的,访问时也是按行索引
CG数据类型:向量float3、float4 矩阵类型:float3x3、float4x4等关键词进行声明和定义