计算机图形学:(六)渲染管线
渲染管线
即渲染流水线,指将数据经过一步步流程最终输出为图像的过程。计算机需要从一系列的顶点数据、纹理等信息出发,把这些信息最终转换成一张人眼可以看到的图像。而这个工作通常是由CPU和GPU共同完成的。
渲染管线的基本结构包含以下四个阶段:① 应用阶段、② 几何处理阶段、③ 光栅化阶段和 ④ 逐像素处理阶段。其中,应用处理阶段主要在CPU上运行,另外三个阶段在GPU上运行。
# 应用阶段
应用阶段主要在CPU上运行,为GPU的渲染管线做准备工作。它是由应用程序进行驱动的,它在软件中进行实现,一般CPU会负责碰撞检测,全局加速算法,动画,物理模拟等任务,具体会执行哪些任务取决于应用程序的类型。
应用阶段大致可分为下面3个阶段:(1)把数据加载到显存中;(2)设置渲染状态和参数;(3)调用Draw Call。
① 数据准备与管理
CPU从硬盘等存储设备读取场景所需的各类数据,如3D模型文件(包含顶点、面片等几何信息)、纹理贴图、Shader、相机参数、光源等,并将这些数据加载到系统的主内存(RAM)中。为了使GPU能够高效地访问和处理这些数据,CPU需要将加载到RAM中的数据传输到显存(VRAM)中,满足GPU在渲染过程中对数据的快速读取需求。
注:当把数据加载到显存中后,RAM中的数据就可以移除了。但对于一些数据来说,CPU仍然需要访问它们(例如,我们希望CPU可以访问网格数据来进行碰撞检测),那么我们可能就不希望这些数据被移除,因为从硬盘加载到RAM的过程是十分耗时的。
除了数据加载,为了提高渲染性能,我们往往需要做一个粗粒度的剔除工作(视锥体剔除、遮挡剔除、层级剔除)。例如CPU会进行视椎体剔除,通过判断物体的AABB包围盒与视锥体的相交情况,来决定是否进行保留,以减少需要处理的图元数量,显著减少GPU的工作量,提高渲染效率。
② 设置渲染状态和参数(SetPass)
通过CPU来设置渲染状态,从而“指导”GPU如何进行渲染工作。这些渲染状态包括但不限于物体使用的材质、光源、纹理、Shader等,而Shader中又包含渲染队列(RenderQueue)、渲染类型(RenderType)等对渲染状态进行更详细的设置。

- 渲染顺序:相对相机距离,材质RenderQueue等;
- 渲染目标:指定渲染结果的输出目标,如:帧缓存(FrameBuffer)、RenderTexture;
- 渲染模式:前向渲染、延迟渲染;
③ 调用Draw Call
Draw Call就是一个命令,它的发起方是CPU,接收方是GPU。这个命令仅仅会指向一个需要被渲染的图元(primitives)列表,而不会再包含任何材质信息。GPU就会根据渲染状态(例如材质、纹理、着色器等)和所有输入的顶点数据来进行计算,最终输出成屏幕上显示的那些漂亮的像素。
但频繁的调用Draw Call会增加CPU和GPU之间的通信开销,降低渲染效率。为了优化渲染:
- (a)CPU会将具有相同材质、纹理和渲染状态的物体合并为一个渲染批次,通过一次Draw Call完成它们的渲染;
- (b)对于具有相同几何形状但不同属性的物体,采用实例化渲染技术,允许GPU在一次Draw Call中渲染多个实例,每个实例的属性通过顶点或实例化属性指定;
- (c)此外,CPU还会合理安排渲染顺序,按物体属性排序以减少状态切换,按距离摄像机的远近排序以及时进行深度测试和剔除操作,避免不必要的渲染计算。
# 几何处理阶段
CPU传输数据到GPU上后,首先会进入几何阶段。几何阶段主要负责处理和转换几何图元(如点、线、三角形等),并为后续的光栅化阶段准备数据

绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。
-
① 顶点着色器
主要工作是坐标变换(把顶点坐标从模型空间转换到齐次裁剪空间)和逐顶点光照。
-
② 曲面细分着色器
通过将曲面进一步划分为更小的子曲面(增加了更多的顶点),可以让模型的细节更加的丰富,显然也是需要更多的资源消耗。
-
③ 几何着色器
把图元形式的一系列顶点的集合作为输入,它可以通过产生新顶点构造出新的(或是其它的)图元来生成其他形状。
-
④ 剪裁
删除不再摄像机视野内的顶点剪裁掉,并剔除某些三角图元的面片。这个阶段是可配置的,例如:我们可以使用自定义的裁剪平面来配置裁剪区域,也可以通过指令控制裁剪三角图元的正面还是背面。
-
⑤ 屏幕映射
从标准设备坐标系(NDC)映射到屏幕坐标系当中。
# 光栅化阶段
光栅化阶段分为两个子阶段:① 三角形设置(又称图元装配)和 ② 三角形遍历。
① 三角形设置
上一个阶段输出的都是三角网格的顶点,即我们得到的是三角网格每条边的两个端点。但如果要得到整个三角网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式,而计算这个边界信息的过程就叫做三角形设置。
② 三角形遍历
三角形遍历阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话,就会生成一个片元(fragment)。
确定三角形覆盖像素区域的方法:对于每个像素,我们都取它的中心点为一个采样点,判断该点是否在三角形内部,若在,则视作该三角形图元覆盖了该中心点所在像素。引申出一个问题:怎么判断点在三角形内?
# 逐像素处理阶段
链接:【科普】什么是Mipmap?
链接:https://zhuanlan.zhihu.com/p/698152095