BlaXuan 发表于 2021-12-20 09:06

UnityShader变换坐标空间和法线

在文章 Unity渲染流水线 一文中,知道了在几何阶段的顶点着色器这一步,GPU会接收来自CPU处理的应用阶段的顶点数据,将每个顶点数据进行坐标转换、逐顶点光照等处理,并把顶点坐标从模型空间转换到齐次裁剪空间,最后经过一系列操作后,输出到屏幕空间。今天来详细了解一下这个转换的过程。
这个转换过程大致流程为:模型空间-> 世界空间 -> 观察空间 -> 裁剪空间 -> 屏幕空间。

[*]模型空间(对象空间、局部空间)
      顾名思义,模型空间即为模型自己的独立空间,模型旋转移动,模型空间也会跟着旋转移动。模型空间的原点和坐标轴通常都是美术在建模的时候就处理好的。可以按照Unity左手坐标系的规则,将模型空间中的+x轴、+y轴、+z轴分别对应模型的右、上、前。这样处理方便客户端计算。




[*]世界空间
Untiy的世界坐标系只有一个,只需在一个空场景下创建一个GameObject,将其坐标设置为(0,0,0)即可找到原点位置。世界坐标系依然使用了左手坐标系。顶点变换的第一步,就是将顶点坐标从模型空间变换到世界空间中。这个过程叫模型变换。shader中可通过内置着色器变量中的 unity_ObjectToWorld矩阵 将模型空间坐标转换到世界空间。
[*]观察空间(摄像机空间)
在所有的模型中有一个非常特殊的模型——摄像机。他决定了我们渲染游戏所使用的视角。在观察空间中,摄像机位于坐标系原点。但是需要注意的是,观察空间使用的是右手坐标系,这是因为这样是符合OpenGL传统的,在观察空间中,摄像机的正前方指向的是-z轴方向。顶点变换的第二步——观察变换,就是将顶点坐标从世界空间转换到观察空间中。shader中可通过内置着色器变量中的 UNITY_MATRIX_V矩阵 将世界空间坐标转换到观察空间。




[*]裁剪空间(齐次裁剪空间)
      此步骤能够根据摄像机的视锥体空间范围来对渲染图元进行裁剪:完全位于视锥体内的图元将被完全保留,与边界相交的图元就会被裁剪,否则将会被剔除。其中,摄像机的视锥体六个面被称为裁剪平面,摄像机的投影类型又分为两种——正交投影和透视投影,投影类型不同,剪裁矩阵的值也不同。



透视投影



正交投影

shader中可通过内置着色器变量中的 UNITY_MATRIX_P矩阵 将观察空间坐标转换到齐次裁剪空间坐标。

[*]屏幕空间
经过投影矩阵的变换和裁剪之后,将齐次裁剪坐标空间通过齐次除法(将齐次坐标系x、y、z分量分别除以w分量,得到得坐标叫归一化的设备坐标)将齐次裁剪空间坐标转换到NDC中。裁剪空间通过齐次除法后会变换到一个立方体内,再OpenGL中此立方体的x、y、z分量范围都为[-1,1],但是在DirectX中,z的分量范围为。Unity选择了OpenGL这样的齐次裁剪空间。



[*]法线变换
法线变换相对与顶点变换较为特殊。一般来说,点和绝大部分方向矢量都可以使用同一个4*4或3*3的变换矩阵将其从坐标空间A变换到坐标空间B中。但对法线来说,直接使用变换顶点的变换矩阵来变换的话,可能会导致变换后的法线与平面不再垂直。
因此,若变换矩阵包含了非统一变换,则我们需要用该变换矩阵的逆转置矩阵来得到变换后的法线才能保证变换后的法线依然与平面垂直。若变换矩阵只包含旋转和统一缩放,那我们可以通过统一缩放系数*变换矩阵的转置矩阵来获得变换后的法线。若变换矩阵只包含旋转变换(正交矩阵),则可以直接用原变换矩阵来变换法线。




[*]切线变换
说到了法线,一定不可避免的提到切线(切矢量)。既然法线变换在转置矩阵包含非统一缩放的时候需要用原变换矩阵的逆转置矩阵来变换,那切线是不是也一样呢?答案是否定的。因为切线是由两个顶点之间的差值计算得到的,因此可以直接用变换顶点的变换矩阵来变换切线。

最后附上unity内置着色器变量链接。内置着色器变量 - Unity 手册

此篇文章是在学习《Unity Shader入门精要》一书的笔记,加入了一些个人理解,如有错误之处,还请各位不吝赐教。
页: [1]
查看完整版本: UnityShader变换坐标空间和法线