一条链没有比其最薄弱的一环更强大   ---匿名

本章介绍了实时图形的核心组件,即图形渲染管道,也简称为“管道”。 管道的主要功能是在给定虚拟相机,三维对象,光源等的情况下生成或渲染二维图像。 因此,渲染管道是用于实时渲染的基础工具。 使用管道的过程如图2.1所示。 图像中对象的位置和形状取决于它们的几何形状,环境的特征以及相机在该环境中的位置。 对象的外观受材质属性,光源,纹理(应用于表面的图像)和着色方程式(shading equations)的影响。

图形渲染管线_unity

图2.1。 在左图中,虚拟摄像头位于金字塔的顶端(四条线汇合处)。 仅渲染视锥体内的图元。 对于透视渲染的图像(此处就是这种情况),视图体积为视锥(复数:视锥),即具有矩形底面的截顶金字塔。 右图显示了相机“看到”的内容。 请注意,左侧图像中的红色甜甜圈形状不在右侧渲染中,因为它位于视锥的外部。 同样,左图中扭曲的蓝色棱柱也被夹在平截头锥体的顶平面上。

我们将解释渲染管道的不同阶段,重点是功能而不是实现。 应用这些阶段的相关细节将在后面的章节中进行介绍。

架构(Architecture)

在物理(physical)世界中,管道概念以许多不同的形式表现出来,从工厂流水线到快餐店厨房。它也适用于图形渲染。管道包含几个阶段,每个阶段执行较大任务的一部分。流水线阶段并行执行,每个阶段取决于上一个阶段的结果。理想情况下,将非流水线系统分成n个流水线级可以使速度提高n倍。性能提升是使用流水线的主要原因。例如,大量的三明治可以由一系列人迅速准备,一个准备面包,另一个添加肉,另一个添加配料。每个都将结果传递给下一个等待的人后,立即开始在下一个三明治上工作。如果每个人花二十秒钟完成他们的任务,每二十秒最多一个三明治,一分钟三个是可能的。流水线并行执行,但它们被暂停直到最慢的阶段完成任务。举例来说,添加肉的阶段变得更加复杂,耗时三十秒。现在可以达到的最佳效率为一分钟就能吃到两个三明治。对于这个特定的管道,添加肉的阶段是瓶颈,因为它决定了整个生产的速度。在添加肉的阶段完成之前,添加配料的阶段将会出现饥饿等待(顾客也是如此)。这种管道构造也可以在实时计算机图形的上下文中找到。实时渲染流水线大致分为四个主要部分应用阶段,几何处理,光珊化和像素处理等阶段如图2.2所示。该结构是渲染管道的核心(引擎)。

图形渲染管线_渲染_02

图2.2。 渲染管道的基本构建包括四个阶段:应用,几何处理,光栅化和像素处理。 这些阶段中的每个阶段都可以是本身,如下面的几何处理阶段所示,或者一个阶段可以(部分)并行化,例如在像素处理阶段下方显示。 在此示例中,应用程序阶段是单个过程,但是此阶段也可以流水线化或并行化。 请注意,光栅化会找到内部的图元像素,例如三角形。

用于实时计算机图形应用程序,因此在后续章节中进行讨论。 这些阶段中的每一个通常本身就是一个管道,这意味着它包含几个子阶段。 我们区分此处显示的功能阶段和其实现的结构。 功能阶段具有要执行的特定任务,但未指定任务的执行方式管道。 给定的实现可以将两个功能阶段组合为一个单元或使用可编程内核执行,而它又划分了另一个更耗时的时间,功能阶段分为几个硬件单元。

渲染速度可以以每秒帧数(FPS)表示,即每秒渲染的图像数。也可以用赫兹(Hz)表示这只是1秒的表示法,即更新频率。也是通常只说明渲染图像所需的时间(以毫秒(ms)为单位)。生成图像的时间通常会有所不同,具体取决于图像的复杂程度。在每个帧中执行的计算。每秒帧数用于表示特定帧的速率或一段时间内的平均性能使用。赫兹用于设置为固定速率的硬件(例如显示器)。顾名思义,应用程序阶段由应用程序驱动,并且是因此通常在通用CPU上运行的软件中实现。这些CPU通常包括能够处理多个线程的多个内核并行执行。这使CPU可以高效地运行各种应用阶段负责的任务。传统上在CPU上执行的一些任务包括碰撞检测,全局加速算法,动画,物理模拟以及许多其他功能,具体取决于应用程序的类型。下一个主要阶段是几何处理,它处理变换,投影,以及所有其他类型的几何处理。这个阶段计算要绘制的内容,应如何绘制以及应在何处绘制。几何阶段通常是在包含许多可编程功能的图形处理单元(GPU)核心以及固定操作的硬件上执行。光栅化阶段通常需要输入三个顶点,形成一个三角形,并找到所有被视为该三角形内部的像素,然后将其转发到下一个阶段。最后是像素处理阶段,每个像素执行一个程序以确定其颜色,并可以执行深度测试看看它是否可见。它还可以执行每个像素的操作,例如将新计算的颜色与以前的颜色混合。光栅化和像素处理阶段也完全在GPU上处理。所有这些阶段及其内部管道将在接下来的四个部分中讨论。有关GPU如何处理这些阶段的内容在第3章中给出。

应用程序阶段

开发人员可以完全控制应用程序阶段发生的事情,因为它通常在CPU上执行。 因此,开发人员可以完全确定实现,以后可以对其进行修改以提高性能。 改变这个阶段也会影响后续阶段的表现。 例如,应用程序阶段算法或设置可能会减少要渲染的三角形数量。

综上所述,GPU可以使用单独的应用程序来执行一些应用程序工作。称为计算着色器的模式。此模式将GPU视为高度并行的通用设备处理器,而忽略其专门用于渲染图形的特殊功能。在应用程序阶段结束时,将要渲染的几何图形输出到几何处理阶段。这些是渲染图元,即点,线和三角形,最终可能会出现在屏幕上(或其他任何正在使用的输出设备)。这是应用程序阶段最重要的任务。此阶段是基于软件实现的结果是不分为子阶段,几何处理,光栅化和像素也是类似的处理阶段。但是,为了提高性能,通常执行此阶段在多个处理器内核上并行运行。在CPU设计中,这称为超标量构造(superscalar
construction),因为它能够在同一时间同时执行多个流程阶段。第18.5节介绍了使用多个处理器内核的各种方法。在此阶段通常实现的一种过程是碰撞检测。之后在两个对象之间检测到碰撞,可能会生成反馈并将其发送到撞击物体以及力反馈装置。应用程序阶段也是处理其他输入来源的地方,例如键盘,鼠标或头戴式显示器。根据此输入,几种不同类型的措施可能发生。加速算法,例如特定的剔除算法(第19章),以及其余管道无法处理的。

几何处理

GPU上的几何处理阶段负责大部分逐三角形和逐顶点的操作。 此阶段进一步分为以下功能阶段:顶点着色,投影,裁剪和屏幕映射(图2.3)

图形渲染管线_渲染_03

图2.3。 几何处理阶段分为功能阶段的流水线。

顶点着色

顶点着色器主要有两个任务,计算顶点的位置和输出一些顶点相关的数据,比如法线和纹理坐标。传统上,通过将光线应用于每个顶点的位置和法线,仅在顶点在存储结果颜色。然后对这些颜色以三角形为单位进行插值。因此,这个可编程的顶点处理单元是命名为顶点着色器。随着现代GPU的出现,所有的着色都发生在每个像素上,这个顶点着色阶段更通用,可能根本不会计算任何着色方程式,这取决于程序员的意图。现在,顶点着色器是一个更通用的单元,专用于设置与每个顶点关联的数据。 例如,使用第4.4节和第4.5节中的方法,顶点着色器可以为对象设置动画。

我们从描述顶点位置的计算方法开始,这是一组坐标,这始终是必需的。在进入屏幕的过程中,模型被转换成多个不同的空间或坐标系。最初,模型驻留在其自己的模型空间中,这仅仅意味着它根本没有被改变。每一个模型都可以进行模型变换(model transform)以至于可以平移和旋转。它可以将多个模型转换与单个模型转换相关联。 这允许同一模型的多个副本(称为实例)具有不同的位置,方向和大小在同一场景中,而无需复制基本几何体。

模型转换的是模型的顶点和法线。 对象的坐标称为模型坐标,在将模型变换应用于这些坐标后,这些模型就被定位在世界坐标或世界空间中。 世界空间是独一无二的,在模型使用各自的模型转换之后
,所有模型都存在于此相同的空间。

如前所述,只有摄像机(或观察者)看到的模型是被呈现出来的。相机在世界空间中有一个位置和一个方向,用于放置并对准相机。为了便于投影和裁剪,相机和所有模型使用视图变换进行变换。视图转换的目的是将相机放在原点并对准它,使其朝着负z轴,y轴指向上方,x轴指向右侧。我们使用-z轴约定;有些文本更喜欢向下看+ z轴。这差异主要是语义上的,因为彼此之间的转换很简单。这应用视图变换后的实际位置和方向取决于在基础应用程序编程接口(API)上。这样划定的空间称为相机空间,或更常见的称为视野空间或眼睛空间。一个例子视图变换影响相机和模型的方式如下所示图2.4

图形渲染管线_渲染_04

图2.4。 在左图中,自上而下的视图显示了摄像机的位置和方向,如用户希望它在正Z轴朝上的世界中成为现实。 视图转换使世界重新定向让相机位于原点,沿其负Z轴看,而相机的正 Y轴朝上,如右图所示。 这样做是为了使裁剪和投影操作更简单,更快捷。浅蓝色区域是视图体积(view volume)。 在此,假定是透视图,因为视图体积是一个视锥体。 类似的技术适用于任何类型的投影。

模型转换和视图转换都可以实现为4×4矩阵,这是第4章的主题。但是,重要的是要认识到,程序员可以通过以任何喜欢的方式计算顶点的位置和法线。

接下来,我们描述顶点着色的第二种输出类型。 为了产生一个逼真的场景,仅渲染对象的形状和位置是不够的,外观也必须建模。 这说明包括每个对象的材质,以及任何光源照在物体上的效果。 材质和灯光以多种方式建模,从简单的颜色到复杂的物理描述图形表示。

光线结合材质决定着效果被称为着色。它涉及计算对象上各个点的着色方程式。 通常,其中一些计算是在模型的几何处理期间执行的,顶点和其他顶点可以在逐像素处理期间执行。 每个顶点可以存储各种材质数据,例如点的位置,法线,颜色,或评估着色方程式所需的任何其他数字信息。顶点着色结果(可以是颜色,向量,纹理坐标以及任何其他种类的着色数据)然后发送到光栅化和像素处理进行插值并用于计算表面着色的阶段。

将以GPU顶点着色器的形式对顶点着色进行更深入的讨论在本书中,尤其是在第3章和第5章中。

作为顶点着色的一部分,渲染系统先进行投影,然后进行裁剪,这会将视图体积转换为一个单位立方体,其极点(extreme points)位于(-1,-1,-1)到(1、1、1)之间。 定义相同体积的不同范围可以并且是例如,0≤z≤1。单位立方称为规范视图体积。
首先进行投影,然后在GPU上通过顶点着色器完成投影。 有两种常用的投影方法,即正交投影(也称为平行投影)透视投影。参见图2.5。 实际上,正交投影只是其中一种平行投影。 还有其他几个用途,尤其是在建筑领域,例如斜投影和轴测投影。 旧的街机游戏Zaxxon被命名为从后者(from the latter)。

图形渲染管线_unity_05

图2.5。 左侧是正交投影或平行投影; 在右边是一个透视投影

请注意,投影表示为矩阵(第4.7节),因此有时与其余的几何变换连接在一起。

正交视图的视图体积通常是一个矩形框,并且正交投影可将此视图体积转换为单位立方体。 正交投影的主要的特点是平行线在转换后仍然保持平行。 此转换是平移和缩放的组合。

透视投影有点复杂。 在这种类型的投影中,物体离相机越远,投影后出现的越小。另外,平行线可能会聚在地平线上。 因此透视变换模仿了我们感知物体尺寸的方式。 从几何学上讲,视图体积称为
截锥体是具有矩形底面的截顶金字塔。

视锥也将转换为单位立方体。 正交变换和透视变换都可以是用4×4矩阵构造(第4章),并在进行任何变换之后,模型处于裁剪坐标系中。 这些实际上是齐次坐标,已讨论在第4章中,因此发生在用w除之前。 GPU的顶点着色器必须总是输出此类型的坐标,以便正常进行下一个功能阶段的裁剪工作。

尽管这些矩阵将一个体积转换为另一个体积,但它们被称为投影,因为在显示之后,z坐标不会存储在生成的图像中,而是存储在z缓冲区中,如第2.5节所述。 通过这种方式,可以对模型进行从三个维度到两个维度投影。

可选的顶点处理

每个流水线都有刚刚描述的顶点处理。 完成此处理后,在GPU上可以按此顺序进行一些可选阶段:细分,几何体着色和流输出。 它们的使用取决于功能硬件-并非所有GPU都具有它们-以及程序员的愿望。 他们彼此独立,通常不常用。 更多会在第3章中对每一个都说一遍。

第一个可选阶段是细分。 假设您有一个弹跳的球物体。如果用一组三角形表示它,则可能会遇到以下问题:质量或性能。 您的球从5米远处看起来可能不错,但近距离各个三角形,尤其是沿轮廓的三角形变得可见。 如果你做带有更多三角形的球以提高质量,可能会浪费大量的处理时间和内存,当球距离很远并且仅覆盖屏幕上的几个像素。通过细分,在曲面上可以生成适当数量的三角形。

我们已经讨论了三角形,但是到目前为止,我们已经有了刚刚处理过的顶点。 这些可以用来表示点,线,三角形或其他对象。 顶点可用于描述曲面,例如球。 这样的曲面可以由一组补丁(patches)指定,每个补丁由一组顶点组成。细分阶段本身包括一系列阶段-壳(Hull)着色器,细分和域着色器-将这些面片顶点集转换为(通常)较大的集的顶点,然后用于制作新的三角形集。 现场摄像机可用于确定生成了多少个三角形:补丁很近的时候多,很远的时候很少。

下一个可选阶段是几何着色器。 该着色器早于曲面细分着色器,因此在GPU上更常见。 就像曲面细分着色器一样因为它输入了各种类型的图元,并且可以产生新的顶点。 它是一个更简单的阶段,因为创建的范围和输出类型受到限制的局限性比输出基础图元要大得多。 几何着色器有多种用途,其中一种最受欢迎的是粒子生成。 想象一下模拟烟花爆炸。

每个火球都可以由一个点,单个顶点表示。 几何着色器可以将每个点都变成面对它的正方形(由两个三角形组成)视口(viewer)并覆盖了几个像素,因此为我们提供了更令人信服的图元着色。

最后一个可选阶段称为流输出。 这个阶段可以让我们使用GPU作为几何引擎。 而不是将处理后的顶点发送到其余的要渲染到屏幕的管道,这时我们可以选择将其输出到用于进一步处理的数组。 这些数据可由CPU或GPU本身使用,在以后的过程中。 此阶段通常用于粒子模拟,例如我们的烟花的例子。

这三个阶段按以下顺序执行:细分,几何体着色,和流输出-每个都是可选的。 无论哪个(如果有)选项是使用过的,如果我们继续沿管线移动,我们会有一组具有齐次坐标的顶点,摄像机视口将会确认它们。

剔除

只要全部或部分包含在视图区内的图元到光栅化阶段(和随后的像素处理阶段),就会在屏幕上绘制它们。完全位于视图体积内的图元将照原样传递到下一个阶段。图元完全不在视线范围内由于未渲染,因此不会进一步传递。正是这些图元部分位于需要裁剪的视图体积之内。例如,一行视图体积的外部一个顶点和内部一个顶点应相对于视图修剪体积,以便将位于外部的顶点替换为位于的新顶点在线条和视图体积之间的交点处。使用投影矩阵表示将变换后的图元剪裁在单位立方体上。这在裁剪之前执行视图转换和投影的优点是它使剔除问题保持一致;图元总是被剪裁在单位立方体里面。

裁剪过程如图2.6所示。 除了六个裁剪视区的平面,用户可以定义其他裁剪平面以明显地裁剪对象。在第818页的图19.1中显示了这种类型的可视化,称为“切片”。

图形渲染管线_unity_06

图2.6。 投影变换后,只有单位立方体内的图元(对于视锥内部的基本图元)是需要继续处理的。 因此,单位立方体外的图元将被丢弃,而完全内部在内部的图元将保留。 与单位立方体相交的图元会被裁剪,从而生成新的顶点并且旧的顶点被丢弃。

裁剪步骤使用投影产生的4值齐次坐标执行裁剪。 值通常不会跨三角形线性插值在透视空间中。 需要第四个坐标,以便在使用透视投影时正确地插值和剪切数据。 最后,透视划分执行,将生成的三角形的位置放到三维空间中规范化的设备坐标。 如前所述,该视图的范围从(-1,-1,-1)至(1、1、1)。 几何阶段的最后一步是从此转换到窗口坐标空间。

屏幕映射

只有视图空间内的(被剪切后)图元传递到屏幕映射阶段,并且进入该阶段时坐标仍然是三维的。每个图元的x和y坐标都将转换为屏幕坐标。屏幕坐标和z坐标也称为窗口坐标。假定场景应渲染到具有最小拐角的窗口中在(x1,y1)和最大角在(x2,y2)处,其中x1 <x2和y1 <y2。 然后屏幕映射是转换,后面是缩放操作。 新的x和y坐标被称为屏幕坐标。 z坐标(对于OpenGL,[-1,+1]并且DirectX的[0,1])也映射到[z1,z2],默认情况下z1 = 0和z2 = 1。 但是,可以使用API进行更改。 窗口沿将此重映射的z值传递给光栅化器阶段。 屏幕映射处理过程如图2.7所示。

图形渲染管线_渲染_07

图2.7。 在投影变换和屏幕映射之后,图元位于单位立方体中该过程需要在屏幕上查找坐标。

接下来,我们描述整数和浮点值与像素(和纹理坐标)。 给定水平像素阵列并使用笛卡尔坐标,在浮点坐标中,最左边像素的左边缘为0.0。 OpenGL一直以来使用了该方案,DirectX 10及其后续版本使用了该方案。 该像素的中心是在0.5。 因此,像素[0,9]的范围覆盖了[0.0,10.0)的范围。 转换是简单地

d = floor(c), (2.1)
c = d + 0.5, (2.2)

其中d是像素的离散(整数)索引,而c是连续(浮点值)。虽然所有API的像素位置值都从左到右增加,但在某些情况下,上边缘和下边缘的零位置不一致OpenGL和DirectX。OpenGL始终偏爱笛卡尔坐标系,左下角是值最低的元素,而DirectX有时会定义左上角作为此元素,具体取决于上下文。 这是一个逻辑,两者的不同并没有谁对谁错之分。 例如,(0,0)位于在OpenGL中图片的左下角,位于DirectX的左上角。 这从一个API迁移到另一个API时,必须考虑到的差异。

光珊化

给定经过变换和投影的顶点及其关联的着色数据(所有来自几何处理),下一阶段的目标是找到所有像素-图片元素-渲染在图元内部(例如三角形)的图片元素。我们将此过程称为光栅化,它分为两个功能子阶段:三角形设置(也称为图元装配)和三角形遍历。这些显示见图2.8。请注意,它们也可以处理点和线,但是由于三角形是最常见的,因此子阶段的名称中带有“三角形”。光栅化也称为扫描转换,因此是从二维顶点的转换屏幕空间-每个都有一个z值(深度值)以及与每个顶点关联的各种着色信息-进入屏幕上的像素。也可以考虑光栅化作为几何处理和像素处理之间的同步点,因为正是在这里,三角形由三个顶点组成,并最终被发送到像素处理。

图形渲染管线_渲染_08

图2.8。 左:光栅化分为两个功能阶段,分别称为“三角形设置”和“三角形”遍历。 右图:像素处理分为两个功能阶段,即像素处理和合并。

三角形是否被视为与像素重叠取决于您设置GPU的管道的方式。 例如,您可以使用点采样来确定“内部”。最简单的情况是在每个点的中心使用一个单点样本像素,因此如果该中心点在三角形内,则对应的像素为也考虑在三角形内部。 您也可以使用一个以上的样本使用超采样或多采样抗混叠技术的像素(第5.4.2节)。另一种方法是使用保守光栅化,其定义是如果像素至少有一部分与三角形重叠,则该像素位于三角形“内部”(第23.1.2节)。

三角形设置

在这个阶段,三角形的微分,边方程和其他数据被计算。 这些数据可用于三角形遍历(第2.4.2节),以及用于内插几何阶段产生的各种着色数据。 固定功能硬件用于此任务。

三角遍历

这是三角形覆盖其中心(或样本)的每个像素的位置检查并为与三角形重叠的像素部分生成一个片段。 更多详细的采样方法可以在第5.4节中找到。 寻找哪个样本或像素位于三角形内部通常称为三角形遍历。 每个三角形片段的属性是在三角形的三个顶点数据之间通过插值生成的(第5章)。 这些属性包括片段的深度以及任何几何阶段的着色数据。 McCormack等。 后面提供了有关三角形遍历的更多信息。 也正是在这里透视校正内插执行三角形(第23.1.1节)。 内部的所有像素或样本然后将图元发送到像素处理阶段,如下所述。

像素处理

此时,在三角形或其他图元内部考虑的所有像素被发现是所有先前阶段相结合的结果。像素处理阶段分为像素着色和合并,如图所示。图2.8。 像素处理是每个像素或每个样本计算的阶段并且对图元内部的像素或样本执行操作。

像素着色

使用插值的着色数据作为输入,在此执行每个像素的着色计算。最终结果是将一种或多种颜色传递到下一个阶段。与通常执行的三角形建立和遍历阶段不同通过专用的硬接线硅(hardwired silicon),像素着色阶段由可编程的程序GPU核心执行。为此,程序员为像素着色器提供了一个程序(或片段着色器(在OpenGL中是众所周知的),它可以包含任何所需的计算。这里可以采用多种技术,其中纹理化是最重要的技术之一。第6章将更详细地讨论纹理化。简单地说,对对象进行纹理化处理意味着将一个或多个图像“粘贴”到该对象上,以实现多种选择目的。图2.9描绘了此过程的一个简单示例。图片可以是一维,二维或三维,其中二维图像最多常见的。最简单的说,最终产品是每个片段的颜色值,而这些传递到下一个子阶段。

图形渲染管线_渲染_09

图2.9。 左上方显示了没有纹理的龙模型。 图片中的碎片将纹理“粘合”到龙上,结果显示在左下方。

合并

每个像素的信息存储在颜色缓冲区中,该缓冲区是一个矩形数组颜色(每种颜色分别是由红色,绿色和蓝色成分组成)。 合并阶段的责任是合并像素着色阶段产生的片段颜色,当前存储在缓冲区中的颜色。 这个阶段也称为ROP,用于“光栅操作(管道)”或“渲染输出单位”的方法,具体取决于您的要求。与着色阶段不同,执行此阶段的GPU子单元通常不完全可编程的。 但是,它是高度可配置的,可实现各种效果。

此阶段还负责解决可见性。这意味着当整个场景都已渲染,颜色缓冲区应包含从相机的角度可见的场景中图元的颜色。对于大多数甚至所有图形硬件,都可以通过z缓冲区(也称为深度缓冲区)来完成
算法。 Z缓冲区的大小和形状与颜色缓冲区相同,对于每个像素将z值存储到当前最接近的图元。这意味着当将图元渲染到某个像素时,该图元的z值正在计算该像素处的,并将其与z缓冲区的内容进行比较。相同的像素。如果新的z值小于z缓冲区中的z值,则正在渲染的图元比以前渲染的图元离相机更近。先前最接近相机的那个像素。因此,该像素的z值和颜色会使用正被绘制的图元的z值和颜色进行更新画。如果计算出的z值大于z缓冲区中的z值,则颜色缓冲区和z缓冲区保持不变。 z-buffer算法很简单,具有O(n)收敛(其中n是要渲染的图元的数量),并且有效适用于任何可以为其计算z值(相关)的绘图图元像素。另请注意,此算法允许大多数原始图元以任何形式进行渲染,这是其受欢迎程度的另一个原因。但是,z缓冲区仅存储一个屏幕上每个点的单一深度,因此不能用于部分透明图元。这些必须在所有不透明的图元之后并从后到前进行渲染,或使用单独的与顺序无关的算法(第5.5节)。有关透明度的渲染是z缓冲区的主要缺点之一。

我们已经提到了颜色缓冲区用于存储颜色,而z缓冲区存储每个像素的z值。 但是,还有其他通道和缓冲区可以用于过滤和捕获片段信息。 Alpha通道已关联颜色缓冲区,并为每个像素存储相关的不透明度值(第5.5节)。在较旧的API中,alpha通道还用于通过alpha测试功能。 如今,可以将丢弃操作插入到像素着色器中程序和任何类型的计算都可以用来触发丢弃。 这类测试可用于确保完全透明的片段不会影响z缓冲区(第6.6节)。

模板缓冲区是一个屏幕外缓冲区,用于记录渲染图元的位置。通常每个像素包含8位。可以使用各种功能将图元渲染到模板缓冲区,然后可以使用缓冲区的内容来控制渲染到颜色缓冲区和z缓冲区中。例如,假设填充圆已被写入模板缓冲区。当这个圆被渲染出来的时候,允许一系列图元被写入颜色缓冲区。模版缓冲区可以是生成某些特殊内容效果的强大工具。流水线末端的所有这些功能都称为栅格操作(ROP)或混合操作。可以混合当前颜色缓冲区中的颜色并在三角形内处理像素的颜色。这可以启用效果例如透明度或颜色样本的累积。如前所述,混合通常可以使用API​​进行配置,并且不能完全编程。但是,有些API支持栅格顺序视图,也称为像素着色器顺序,启用可编程的混合功能。

帧缓冲区通常由系统上的所有缓冲区组成。

当图元到达并通过光栅化程序阶段时,从相机的角度看得见的图像显示在屏幕上。 屏幕显示颜色缓冲区的内容。 为了避免让观众看到在对图元进行栅格化并将其发送到屏幕的过程,双重缓冲被使用。 这意味着场景的渲染发生在屏幕后方的缓冲区中。将场景渲染到后台缓冲区中后,后台缓冲区的内容和先前显示在前面的缓冲区的内容交换屏幕。 交换通常发生在垂直回扫期间,即安全的时候这样做。有关不同缓冲区和缓冲方法的更多信息,请参见第5.4.2节,23.6和23.7。

通过管道

点,线和三角形是模型或已建立的渲染图元对象。 想象一下,该应用程序是一种交互式计算机辅助设计(CAD)应用程序,并且用户正在检查华夫饼机的设计。 这里我们将在整个图形渲染管道中遵循该模型,包括四个主要阶段:应用程序,几何,光栅化和像素处理。 这场景将透视图渲染到屏幕上的窗口中。 在这个简单的例子中,华夫饼制作机模型同时包含线条(以显示零件的边缘)和三角形(以显示表面)。 松饼机的盖子可以打开。 某些三角形通过带有制造商徽标的二维图像进行纹理处理。 为了在此示例中,表面着色是在几何阶段完全计算的,除了应用于在光栅化阶段发生的纹理。

应用

CAD应用程序允许用户选择和移动模型的各个部分。 例如,用户可以选择盖子,然后移动鼠标将其打开。 应用程序阶段必须将鼠标移动转换为相应的旋转矩阵,然后确认呈现该矩阵时已将其正确应用于盖子。 另一个例子:播放动画,使摄像机沿预定义的路径移动以显示华夫饼干制造商从不同的角度。 摄像机参数,例如位置和视图方向,然后必须由应用程序根据时间进行更新。 对于每个要渲染的帧,应用程序阶段会输入相机的位置,光线和模型的图元到管道的下一个主要阶段-几何阶段。

几何处理

对于透视图,我们在这里假设应用程序已经提供了一个投影矩阵。此外,对于每个对象,应用程序都已计算出一个矩阵,该矩阵描述了视图变换以及对象本身的位置和方向。在我们的示例中,华夫饼制造商的底座将具有一个矩阵,而盖子则具有另一个矩阵。在几何图形阶段,对象的顶点和法线将以此进行变换矩阵,将对象放入视图空间。然后在进行着色或其他计算可以使用材质和光源属性来计算顶点。投影使用程序员单独提供的投影矩阵执行将对象放到代表眼睛所见的单位立方体的空间中。为了获得一组完全位于单位立方体内部的图元,所有单位立方体外面的图元被丢弃。所有与该单位立方体相交的图元均被裁剪。然后将这些顶点映射到屏幕上的窗口中。在完成所有这些三角形和逐顶点的操作之后,将传递结果数据进入光栅化阶段。

光珊化

然后将所有在上一阶段裁剪后幸存的图元栅格化,从而表示找到了图元内部的所有像素,并将其进一步发送到像素处理的流水线。

像素处理

此处的目标是计算每个可见图元的每个像素的颜色。 这些与任何纹理(图像)相关联的三角形将被渲染图像根据需要应用于它们。 可见性是通过z缓冲区算法解决的,以及可选的丢弃和模版测试。 每个对象依次处理,并且最终图像将显示在屏幕上。

总结

该管道源于数十年来针对API和图形硬件的发展 实时渲染应用程序。重要的是要注意,这不是唯一的 可能的渲染管道;离线渲染管道经历了不同的演变路径。电影制作的渲染通常是使用微多边形完成的 管道,但光线跟踪和路径跟踪近来已被接管。这些技术(在第11.2.2节中介绍)也可以用于建筑和设计中 预可视化。 多年来,应用程序开发人员使用描述的过程的唯一方法 这是通过使用中的图形API定义的固定功能管道完成的。这 固定功能管道之所以如此命名是因为实现它的图形硬件 由无法灵活编程的元素组成。最后一个例子 主要的固定功能机器是2006年推出的任天堂Wii。 另一方面,GPU使确定确切的操作是可能的 ,应用于整个管道的各个子阶段。对于第四版 在本书中,我们假设所有开发都是使用可编程GPU完成的。

进一步阅读和资源

Blinn的著作A Trip Down the Graphics Pipeline《图形流水线之旅》 是一本关于从像素实现软件渲染的旧书。 这是学习以下内容的好资源实现渲染管线的精妙之处,解释了关键算法,例如作为裁剪和透视插值。 过去的(至今还经常更新)OpenGL编程指南(又称“红皮书”)提供了图形管道的完整描述以及与其使用相关的算法。 我们书的网站,realtimerendering.com,提供指向各种管线图的链接,渲染引擎实现等等。