Unity 之渲染管线初探
Unity 是一款跨平台的 3D 引擎,具备强大的渲染功能,广泛应用于游戏开发领域。在探讨 Unity 的渲染功能时,着色器(Shader)是绕不开的重要概念。它是 3D 游戏引擎中至关重要的因素,对游戏效果和画面显示起着决定性作用。Shader 编程也是计算机图形学的重要组成部分。接下来,我们将从可编程渲染管线的角度深入了解 Shader 编程。
渲染管线模型
3D 游戏和 3D 模型通过渲染管线最终呈现在 2D 屏幕上。渲染管线的处理流程在 GPU 中进行,主要占用计算机的显存。在这个过程中,渲染管线依次完成顶点处理、面处理、光栅化和像素处理。
1. 顶点处理
对于接触过 3D 图形的人来说,都清楚 3D 模型是由众多点构成的面组合而成。顶点处理是通过一系列坐标系的变换,使各个顶点按照一定规律在摄像机前移动,最终在屏幕上找到对应位置的过程。
具体而言,物体的各个顶点首先从自身坐标系出发,经过世界变换矩阵的处理转换到世界坐标系;接着,通过取景变换矩阵变换到观察者坐标系;最后,经过投影变换,将顶点转移到屏幕坐标系。需要注意的是,在从观察者坐标系转换到投影坐标系的过程中,GPU(图形处理单元)还会对材质属性和光照属性进行处理。
2. 面处理
三点确定一个面,面处理主要包括面的组装、面的截取和面的剔除三个部分。
- 面的组装:模型中的三个特定点(每个点都有唯一编号)会组成一个三角形面,这些面相互连接,共同构成了我们所看到的模型。
- 面的截取:由于摄像机的可视区域类似人眼,呈锥形,模型在摄像机可视范围内可能并非完全覆盖,位于摄像机外的部分将被截取。
- 面的剔除:为了模拟肉眼的视觉效果,摄像机前的物体呈现近大远小的现象,物体之间会存在遮挡关系,被遮挡的面将被剔除,不再进行处理。每个面都有法向量,只有当该面的法向量与摄像机散射向量的夹角大于 90 度时,才会被摄像机捕捉到。
3. 光栅化
光栅化也被称为合并阶段,其主要功能是将面转换为一帧中的像素集合。这一阶段不可编程,但会执行多个片段测试,包括深度测试、alpha 测试和模板测试。程序员可以通过高级配置来实现特定效果。如果通过了所有测试,该部分颜色将与帧缓冲存储的颜色通过 alpha 混合函数进行合并。
4. 像素处理
此阶段的主要任务是对像素区域进行着色,并赋予贴图。
(左上为 3D 网格模型,左下为赋予贴图后的 3D 模型,右图为贴图)
Shader 详解
在了解了 GPU 渲染管线之后,我们来深入探究可编程着色器 Shader,它是图形渲染中极具趣味性的部分。Shader 能够让渲染的图形呈现出水面效果、火焰热流效果、角色虚化效果等丰富的视觉效果。
着色器主要分为顶点着色器(VertexShader)、几何着色器(Geometry Shader)和像素着色器(Pixel Shader)。它们从输入数据中获取一个元素,经过程序计算,将其转换为输出数据的一个或多个元素。
- 顶点着色器:输入源为顶点,顶点包含其在自身坐标系或世界坐标系中的位置和矢量信息;输出源为经过变换和照明处理的顶点,包含其在投影坐标系中的信息。
- 几何着色器:输入源为一个包含 n 个顶点的几何图元以及最多 n 个作为控制点的额外顶点;输出源则为 0 个或多个图元,这些图元的类型可能根据效果需求与输入时不同。
- 像素着色器:输入为顶点间的片段,这些片段的信息来自对三角形顶点信息的插值;输出为将要写入帧缓冲的颜色。
结语
在游戏中,绚丽的场景和角色是如何实现的呢?其实很简单,纹理数据是通过纹理坐标(UV 坐标)进行寻址,而非内存地址。通过着色器,我们可以直接读取纹理贴图。模型的顶点与纹理内的 UV 坐标一一对应,这样纹理就能按照一定规则贴在模型上。