Unity Shader数学基础

本篇介绍的是坐标系及不同坐标系间通过矩阵进行转换

坐标系和旋转正向

左手坐标系和右手坐标系

Unity使用左手系,但是对于观察空间来说,Unity使用的是右手坐标系,摄像机的前向是z轴的负方向

矩阵

转置矩阵性质:

  • 转置矩阵的转置等于原矩阵

  • 矩阵串接的转置等于反向串接各个矩阵的转置

逆矩阵性质:

  • 原矩阵乘转置矩阵为单位矩阵

  • 逆矩阵的逆矩阵是原矩阵

  • 单位矩阵的逆矩阵是本身

  • 转置矩阵的逆矩阵是逆矩阵的转置

判断可逆:矩阵的行列式不为0

正交矩阵性质:

  • 矩阵的每一行都是单位矢量

  • 矩阵的每一行相互垂直

  • 对列一样适用

正交:矩阵乘转置矩阵是单位矩阵 也就是转置矩阵等于逆矩阵

一个正交矩阵的行和列之间分别构成了一组标准正交基,但如果使用一组正交基来构建一个矩阵的话,这个矩阵就不一定是正交矩阵

矩阵变换

包括平移,缩放,旋转等基础变换

复合变换,约定变换顺序:先缩放,再旋转,后平移

坐标系变换

假设两个坐标空间A,B

从A空间变换到B空间的矩阵:就是A空间的X,Y,Z轴在父空间下的矢量表示 按列

B空间到A空间 就是按行

顶点的坐标空间变换过程

模型空间

每个物体自身的局部空间,Unity在模型空间是左手系,模型的顶点都是相对于模型空间的原点定义的

世界空间

观察空间

摄像机的本地空间,遵循右手系,符号OpenGL传统,摄像机的正前方指向的是-z轴方向。

观察空间是三维空间,屏幕空间是二维空间,通过投影变换进行转换

为了得到顶点在观察空间的位置,两种方法:

  1. 计算观察空间3个坐标轴在世界空间下的表示,然后构建从观察空间变换到世界空间的变换矩阵,再对该矩阵进行求逆。

  2. 想象摄像机是从世界原点经过怎样的变换变换到现在的位置,然后用逆变换变换回去。

裁剪空间

顶点接下来要从观察空间变换到裁剪空间,用于变换的矩阵为裁剪矩阵,也叫做投影矩阵

裁剪空间的目标是能够方便地对渲染图元进行裁剪,根据视锥体(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等关键词进行声明和定义


Unity Shader数学基础
https://shanhainanhua.github.io/2023/04/23/Unity-Shader数学基础/
作者
wantong
发布于
2023年4月23日
许可协议