实时渲染
2. 图形渲染管线
链条的坚固程度取决于它最薄弱的环节。 --匿名者
本章介绍实时图形渲染的核心组件,即图形渲染管线,也简称为“管线”。管线的主要功能是通过给定虚拟相机、三维对象、光源等,生成或渲染二维图像。因此,渲染管线是实时渲染的基础工具。使用管线的过程如图2.1所示。图像中对象的位置和形状由它们的几何形状、环境特征以及相机在该环境中的位置决定。对象的外观受材料属性、光源、纹理(应用于表面的图像)和着色方程的影响。
图2.1. 在左图中,一个虚拟相机位于金字塔的顶端(四条线会聚的地方)。仅渲染视图体积内的图元。对于透视渲染的图像(如这里的情况),视图体积是一个平截头体(frustum,复数为frusta),即具有矩形底部的截棱锥。右图显示了相机“看到”的内容。请注意,左侧图像中的红色甜甜圈形状不在右侧的渲染中,因为它位于视锥体之外。此外,左图中扭曲的蓝色棱镜被剪裁在平截头体的顶平面上。
我们将解释渲染管线的不同阶段,重点是功能而不是实现。应用这些阶段的相关细节将在后面的章节中介绍。
2.1 架构
在现实世界中,管线的概念以许多不同的形式表现出来,从工厂装配线到快餐厨房。它也适用于图形渲染。管线由几个阶段组成[715],每个阶段执行一个更大任务的一部分。
每一个流水线阶段都是并行执行,但是其都依赖于前一阶段的结果。理想情况下,一个非流水线系统然后被分成n个流水线级,可以提供n倍的加速。这种性能的提高是使用流水线的主要原因。例如,可以由一系列人快速准备大量三明治——一个准备面包,另一个添加肉,另一个添加浇头。每个人都将结果传递给排队的下一个人,然后立即开始制作下一个三明治。如果每个人需要20秒来完成他们的任务,那么每20秒一个三明治的最大速度是可能的,每分钟三个。流水线阶段并行执行,但它们会暂停,直到最慢的阶段完成其任务。例如,假设肉类添加阶段变得更加复杂,需要30秒。现在可以达到的最佳速度是每分钟两个三明治。对于这个特定的管线,肉阶段是瓶颈,因为它决定了整个生产的速度。据说浇头阶段在等待肉类阶段完成期间饿死了(顾客也是如此)。
这种管线结构也可以在实时计算机图形的上下文中找到。实时渲染管线粗略划分为四个主要阶段——应用程序、几何处理、光栅化和像素处理——如图2.2所示。渲染管线引擎用于实时计算机图形应用程序,其核心正是这种结构;因此这种管线结构是后续章节讨论的重要基础。这些阶段中的每一个通常本身就是一个管道,这意味着它由几个子阶段组成。我们区分此处显示的功能阶段及其实现结构。一个功能阶段有一个特定的任务要执行,但没有指定任务在管道中的执行方式。一个给定的实现可以将两个功能阶段合并为一个单元或使用可编程内核执行,同时它将另一个更耗时的功能阶段划分为几个硬件单元。
图2.2. 渲染管线的基本结构,包括四个阶段:应用程序、几何处理、光栅化和像素处理。这些阶段中的每一个本身都可以是一个流水线,如几何处理阶段下方所示,或者一个阶段可以(部分)并行化,如像素处理阶段下方所示。在这个例子中,应用程序阶段是一个单一的进程,但这个阶段也可以是流水线或并行的。请注意,光栅化阶段会查找图元内部的像素,例如三角形。
渲染速度可以用每秒帧数(FPS)来表示,即每秒渲染的图像数量。也可以用赫兹(Hz)来表示,它只是1/秒的表示法,即更新频率。仅说明渲染图像所需的时间(以毫秒(ms)为单位)也很常见。生成图像的时间通常会有所不同,具体取决于每帧期间执行的计算的复杂性。每秒帧数用于表示特定帧的速率或一段时间内的平均性能。赫兹用于硬件,例如设置为固定速率的显示器。
顾名思义,应用程序阶段由应用程序驱动,因此通常在通用CPU上运行的软件中实现。这些CPU通常包括能够并行处理多个执行线程的多个内核。这使CPU能够有效地运行由应用程序阶段负责的各种任务。一些传统上在CPU上执行的任务包括碰撞检测、全局加速算法、动画、物理模拟等,具体取决于应用程序的类型。下一个主要阶段是几何处理,它处理变换、投影和所有其他类型的几何处理。此阶段计算要绘制的内容、应如何绘制以及应在何处绘制。几何阶段通常在包含许多可编程内核和固定操作硬件的图形处理单元(GPU)上执行。光栅化阶段通常将三个顶点作为输入,形成一个三角形,并找到该三角形内的所有像素,然后将这些像素转发到下一个阶段。最后,像素处理阶段对每个像素执行一个程序以确定其颜色,并可能执行深度测试以查看它是否可见。它还可以执行逐像素操作,例如将新计算的颜色与先前的颜色混合。光栅化和像素处理阶段也完全在GPU上处理。所有这些阶段及其内部管道将在接下来的四节中讨论。有关GPU如何处理这些阶段的更多详细信息,请参见第3章。