Real-time Rendering (3rd edition)学习笔记第1-2章

本博文仅作学习使用,欢迎学习渲染和计算机图形学的朋友相互讨论。

第1章 介绍

实时渲染是指在计算机上快速生成图像。它是计算机图形学中交互性最强的领域。一个图像出现在屏幕上,观众的行为或反应,这种反馈会影响接下来生成的内容。这个反应和渲染的循环以足够快的速度发生,以至于观察者看不到单独的图像,而是沉浸在一个动态的过程中。图像显示的速率是以帧每秒(fps)或赫兹(Hz)为单位的。在每秒一帧的情况下,几乎没有互动的感觉;用户痛苦地意识到每个新映像的到来。在6帧左右时,互动性开始增强。以15帧/秒速度显示的应用程序当然是实时的;用户关注行动和反应。然而,有一个有用的限制。从72fps起,显示速率的差异实际上是无法察觉的。观看图像以每秒60帧的速度闪烁是可以接受的,但是更高的频率对于最小化响应时间是非常重要的。仅仅15毫秒的时间延迟就会使交互变慢并干扰交互[1329]。实时渲染比交互性更重要。如果速度是唯一的标准,那么任何快速响应用户命令并在屏幕上绘制任何内容的应用程序都是合格的。实时渲染通常是指三维渲染。交互性和与三维空间的某种联系是实时渲染的充分条件,但第三个元素已经成为其定义的一部分:图形加速硬件。虽然专门用于三维图形的硬件已在专业工作站中使用多年,但直到最近才有可能在消费者层面上使用这种加速器。许多人认为1996年3Dfx Voodoo 1的引入是这个时代的真正开端[297]。随着这个市场的快速发展,附加的三维图形加速器就像一对扬声器一样成为家庭电脑的标准配置。虽然它不是实时渲染所绝对需要的,但是图形加速硬件已经成为大多数实时应用程序的需求。由硬件加速实现的实时渲染结果的一个很好的示例如图1.1所示。
图1.1一个来自玩具店演示[1246,1247,1249]的精彩图像,以交互速率生成。(图片由Natalya Tatarchuk, ATI Research, Inc.提供)
在过去的几年中,图形硬件的进步推动了交互式计算机图形学领域的研究激增。 我们将专注于提供提高速度和改善图像质量的方法,同时还将描述加速算法和图形API的功能和局限性。 我们将无法深入讨论每个主题,因此我们的目标是介绍概念和术语,了解如何以及何时可以应用各种方法,并提供指向寻求更深入信息的最佳位置的指针。 我们希望我们为您提供理解该领域的工具的尝试被证明值得您花在我们的书上的时间和精力。

1.1 内容概括

下面是对前面章节的简要概述:
第2章,图形渲染管道。本章讨论实时渲染的核心,即获取场景描述并将其转换为我们可以看到的内容的机制。
第3章,图形处理单元。现代GPU使用固定功能和可编程单元的组合来实现渲染管线的各个阶段。
第4章,转换。变换是用于操纵对象的位置,方向,大小和形状以及相机的位置和视图的基本工具。
第5章,外观。本章开始讨论材料和灯光的定义及其在实现逼真的表面外观中的用途。还涉及其他与外观相关的主题,例如通过抗锯齿和伽玛校正提供更高的图像质量。
第6章,纹理化。实时渲染最强大的工具之一是能够快速访问和显示表面上的图像等数据。本章讨论了这种技术(称为纹理化)的机制,并提出了多种应用该方法的方法。
第7章,高级着色。本章讨论正确表示材料和点光源的使用的理论和实践。
第8章,区域和环境照明。本章将探讨更详细的光源和算法。
第9章,全局照明。讨论了阴影,反射和折射算法,以及诸如辐射度,射线追踪,预先计算的照明和环境光遮挡等主题。
第10章,基于图像的效果。多边形并非总是描述物体或现象(例如镜头光晕或火焰)的最快或最现实的方式。在本章中,将讨论基于使用图像的替代表示。还涵盖了后处理效果,例如高动态范围渲染,运动模糊和景深。
第11章,非真实感渲染。尝试使场景看起来逼真只是渲染它的一种方法。本章讨论其他样式,例如卡通阴影。
第12章,多边形技术。几何数据来自多种来源,有时需要进行修改才能快速,良好地呈现。本章讨论多边形数据以及清理和简化多边形的方法。还包括更紧凑的表示形式,例如三角形条,扇形和网格。
第13章,曲线和曲面。硬件最终会处理点,线和面以渲染几何图形。更复杂的表面具有诸如能够在质量和渲染速度之间折衷,更紧凑的表示以及平滑的表面生成等优点。
第14章,加速算法。完成后,使其快速运行。这里介绍了各种形式的剔除和细节渲染级别。
第15章,管道优化。一旦应用程序运行并使用高效的算法,就可以使用各种优化技术使其更快。本章主要是关于查找瓶颈并决定如何处理。还讨论了多处理。
第16章,相交测试方法。交叉口测试对于渲染,用户交互和碰撞检测很重要。此处提供了针对常见几何相交测试的各种最有效算法的深入介绍。
第17章,冲突检测。找出两个对象是否彼此接触是许多实时应用程序的关键要素。本章介绍了这个不断发展的领域中的一些有效算法。
第18章,图形硬件。虽然在先前的章节中已经讨论了GPU加速算法,但本章重点介绍诸如颜色深度,帧缓冲区和基本体系结构类型之类的组件。提供了一些代表性图形加速器的案例研究。
第19章,未来。猜一猜(我们知道)。
我们已包含有关线性代数和三角学的附录。

1.2 符号和定义

首先,我们将解释本书中使用的数学符号。有关本节中使用的许多术语的更详细解释,请参见
附录A。(本节略,详情看原文)

1.2.1 数学符号

表1.1总结了我们将使用的大多数数学符号。
表1.2给出了一些额外的数学运算符及其符号。
表1.3一些特殊数学函数的符号.

1.2.2 几何定义

大多数图形硬件使用的基本渲染图元(也称为绘图图元)是点,线和三角形。在整本书中,我们将几何实体的集合称为模型(model)对象(object)场景(sence) 是模型的集合,其中包括要渲染的环境中包含的所有内容。 场景还可以包括材质说明,照明和查看规格。 对象的示例是汽车,建筑物甚至直线。 在实践中,对象通常由一组绘图图元组成,但并非总是如此。 一个对象可能具有更高的几何表示形式,例如Bezier曲线或曲面,细分曲面等。而且,对象可以由其他对象组成,例如,我们称汽车模型门为对象或汽车子集 。

进一步阅读和参考资料

我们可以参考的最重要的资源是本书的网站:http://www.realtimerendering.com。它包含链接到最新的信息和网站相关的每一章。实时绘制领域随着实时速度的变化而变化。在这本书中,我们试图把重点放在基本的概念和技术,不太可能过时。在网站上,我们有机会展示与当今软件开发人员相关的信息,我们有能力保持最新。

第2章 图形渲染管道

“A chain is no stronger than its weakest link.”—Anonymous
本章介绍了实时图形的核心组件,即图形渲染管道(graphics rendering pipeline),也简称为管道( pipeline)。 流水线的主要功能是在给定虚拟相机,三维对象,光源,阴影方程,纹理等的情况下生成或渲染(render)二维图像。 因此,渲染管道是用于实时渲染的基础工具。 使用管道的过程如图2.1所示。 图像中对象的位置和形状取决于它们的几何形状,环境的特征以及相机在该环境中的位置。 对象的外观受材质属性,光源,纹理和阴影模型的影响。
现在将讨论和解释渲染管线的不同阶段,重点是功能而不是实现。 实现细节要么留给以后的章节使用,要么是程序员无法控制的元素。 例如,对于使用线的人来说,重要的是诸如顶点数据格式,颜色和图案类型之类的特征,以及例如是否可以使用深度提示,而不是通过Bresenham的线描算法[142]实现线还是 通过对称双步算法[1391]。 通常,这些流水线阶段中的某些阶段是在非可编程硬件中实现的,这使得无法优化或改进实现。 基本绘制和填充算法的详细信息在Rogers [1077]等书中有详细介绍。 尽管我们可能无法控制某些底层硬件,但是算法和编码方法对生成图像的速度和质量有重大影响。
图2.1 在左图中,一台虚拟摄像机位于金字塔的顶端(四条线汇合处)。 仅渲染视图体内的图元。 对于透视渲染的图像(此处就是这种情况),视图体积为平截头体,即具有矩形底面的截顶金字塔。 右图显示了相机所见。 请注意,左侧图像中的红色甜甜圈形状不在右侧渲染中,因为它位于视锥的外部。 同样,左图中扭曲的蓝色棱柱也被夹在视锥的顶面上。

2.1 架构

在物理世界中,管道概念以许多不同的形式体现出来,从工厂装配线到滑雪缆车。 它也适用于图形渲染。 管道包括几个阶段[541]。 例如,在输油管道中,直到已经在该第二阶段中的油移至第三阶段,油才能从管道的第一阶段移至第二阶段。 这意味着无论其他阶段有多快,流水线的速度都由最慢的阶段决定。理想情况下,一个非流水线的系统被划分为n个流水线的阶段,可以使速度提高n倍。 性能的提高是使用流水线的主要原因。 例如,仅包含一把椅子的滑雪吊椅效率低下; 增加更多的椅子可以使上坡滑雪者的数量成比例地增加。 流水线阶段并行执行,但是直到最慢的阶段完成其任务之前,它们都会暂停。 例如,如果在汽车装配线上的方向盘安装阶段花费3分钟,而每隔一个阶段花费2分钟,则可以达到的最佳速度是每3分钟生产一辆汽车。 方向盘固定完成后,其他阶段必须闲置一分钟。 对于这种特殊的管道,方向盘级是瓶颈(bottleneck),因为它决定了整个生产的速度。
这种管道构造也可以在实时计算机图形的上下文中找到。实时渲染管线大致分为三个概念阶段:应用程序(conceptual stages—application),几何(geometry)和光栅化器(rasterizer),如图2.2所示。这种结构是实时计算机图形应用程序中使用的渲染管道引擎的核心,因此是后续各章讨论的重要基础。这些阶段中的每个阶段通常本身就是一个管道,这意味着它由几个子阶段组成。我们在概念阶段(应用程序,几何和光栅化程序),功能阶段和管线阶段之间进行区分。功能阶段具有要执行的特定任务,但未指定在管道中执行任务的方式。另一方面,流水线阶段与所有其他流水线阶段同时执行。流水线阶段也可以并行化以满足高性能需求。例如,几何阶段可以划分为五个功能阶段,但是图形系统的实现决定了将其划分为流水线阶段。给定的实现可以将两个功能阶段组合到一个流水线阶段,而又将另一个耗时的功能阶段划分为几个流水线阶段,甚至将其并行化。
图2.2 渲染管道的基本构造,包括三个阶段:应用、几何和光栅化。每个阶段本身可能是一个管道,如下面的几何阶段所示,或者一个阶段可能(部分)被并行化,如下面的光栅化阶段所示。在这个示例中,应用程序阶段是单个进程,但是这个阶段也可以是流水线或并行化的。
这是最慢的流水线阶段,它决定了渲染速度(rendering speed),图像的更新速率。 该速度可以表示为每秒的帧数(fps),即每秒渲染的图像数。 也可以使用赫兹(Hz)来表示,它只是1/秒的表示法,即更新频率。 应用程序生成图像所用的时间通常会有所不同,具体取决于每个帧期间执行的计算的复杂性。 每秒帧数用于表示特定帧的速率,或表示在使用期间的平均性能。 赫兹用于设置为固定速率的硬件(例如显示器)。 由于我们正在处理管道,因此加起来要渲染的所有数据通过整个管道所花费的时间是不够的。当然,这是管道构造的结果,该构造允许各阶段并行执行。 如果我们能够找到瓶颈,即管道最慢的阶段,并测量数据通过该阶段所花费的时间,那么我们可以计算渲染速度。 例如,假设瓶颈阶段需要20ms(milliseconds)的时间来执行; 那么渲染速度将为1 / 0.020 = 50 Hz。 但是,只有在输出设备可以此特定速度更新时,这才成立。 否则,真实的输出速率将变慢。 在其他流水线上下文中,使用术语吞吐量(throughput)而不是渲染速度。
示例:渲染速度。 假设我们的输出设备的最大更新频率为60 Hz,并且发现了渲染管道的瓶颈。 时间显示该阶段需要62.5 ms的时间来执行。 然后,如下计算渲染速度。 首先,忽略输出设备,我们得到的最大渲染速度为1 / 0.0625 = 16 fps。 其次,将该值调整为输出设备的频率:60 Hz表示渲染速度可以为60 Hz,60/2 = 30 Hz,60/3 = 20 Hz,60/4 = 15 Hz,60/5 = 12 Hz,依此类推。 这意味着我们可以预期渲染速度为15 Hz,因为这是输出设备可以管理的最大恒定速度,小于16 fps。
顾名思义,应用程序阶段(application stage)由应用程序驱动,因此是在通用CPU上运行的软件中实现的。这些CPU通常包括多个内核,这些内核能够并行处理多个执行(execution)线程(threads)。这使CPU可以有效地运行应用程序阶段负责的各种任务。传统上在CPU上执行的某些任务包括碰撞检测,全局加速算法,动画,物理模拟以及许多其他任务,具体取决于应用程序的类型。下一步是几何阶段(geometry stage),它处理变换,投影等。此阶段计算要绘制的内容,应如何绘制以及应在何处绘制。几何阶段通常在包含许多可编程内核以及固定操作硬件的图形处理单元(GPU)上执行。最后,光栅化器阶段(rasterizer stage)使用前一阶段生成的数据以及所需的任何按像素计算来绘制(渲染)图像。光栅化程序阶段在GPU上完全处理。这些阶段及其内部管道将在接下来的三个部分中讨论。有关GPU如何处理这些阶段的更多详细信息,请参阅第3章。

2.2 应用程序阶段

由于它在CPU上执行,因此开发人员可以完全控制应用程序阶段发生的事情。 因此,开发人员可以完全确定实现,以后可以对其进行修改以提高性能。 此处的更改也会影响后续阶段的性能。 例如,应用程序阶段算法或设置可以减少要渲染的三角形的数量。在应用程序阶段结束时,要渲染的几何图形被馈送到几何图形阶段。 这些是渲染图元(rendering primitives),即点,线和三角形,它们最终可能最终出现在屏幕上(或使用的任何输出设备)。 这是应用程序阶段最重要的任务。 此阶段基于软件的实现的结果是,与几何阶段和光栅化阶段一样,它并未分为多个子阶段。但是,为了提高性能,该阶段通常在多个处理器内核上并行执行。 在CPU设计中,这被称为超标量构造(superscalar),因为它能够在同一阶段同时执行多个进程。 15.5节介绍了利用多个处理器内核的各种方法。在此阶段通常实施的一种过程是冲突检测(collision detection)。 在两个物体之间检测到碰撞之后,可以生成响应并将其发送回碰撞的物体以及力反馈设备。 在应用程序阶段还应注意其他来源的输入,例如键盘,鼠标,头戴式头盔等。根据此输入,可以采取几种不同的操作。 在此阶段中实现的其他过程包括纹理动画,通过变换的动画或在任何其他阶段中未执行的任何类型的计算。 这里也实现了加速算法,例如层次视图视锥筛选(请参阅第14章)。

2.3 几何阶段

几何阶段负责每个多边形和顶点操作。 该阶段进一步分为以下功能阶段:模型和视图变换,顶点着色,投影,修剪和屏幕映射(图2.3)。 再次注意,根据实现方式,这些功能阶段可能等同于或可能不等同于流水线阶段。 在某些情况下,多个连续的功能阶段形成单个管道阶段(与其他管道阶段并行运行)。 在其他情况下,功能阶段可以细分为几个较小的流水线阶段。
图2.3 几何阶段细分为功能阶段的流水线。
例如,在一个极端情况下,整个渲染管道中的所有阶段都可以在单个处理器上的软件中运行,然后您可以说整个管道由一个管道阶段组成。 当然,这是在单独的加速器芯片和电路板问世之前生成所有图形的方式。 在另一个极端,每个功能阶段可以细分为几个较小的流水线阶段,并且每个这样的流水线阶段都可以在指定的处理器核心元素上执行。

2.3.1 模型和视图转换

在进入屏幕的过程中,一个模型被转换为几个不同的空间(spaces)或坐标系(coordinate systems)。 最初,模型驻留在其自己的模型空间中,这仅表示该模型根本没有进行转换。 每个模型都可以与模型转换相关联,以便可以定位和定向。 可能有多个模型转换与单个模型相关联。 这允许同一模型的多个副本(称为实例)在同一场景中具有不同的位置,方向和大小,而无需复制基本几何图形。
通过模型变换变换的是模型的顶点和法线。 对象的坐标称为模型坐标,并且在将模型转换应用于这些坐标之后,可以说模型位于世界坐标或世界空间中。 世界空间是唯一的,在对模型进行了各自的模型转换后,所有模型都存在于同一空间中。
模型的顶点和法线通过模型变换进行变换。 对象的坐标称为模型坐标(model coordinates),并且在将模型转换应用于这些坐标之后,可以说模型位于世界坐标(world coordinates)或世界空间(world space)中。 世界空间是唯一的,在对模型进行了各自的模型转换后,所有模型都存在于同一空间中。
如前所述,仅渲染摄像机(或观察者)看到的模型。 相机在世界空间和方向中具有一定的位置,用于放置和对准相机。 为了便于投影和裁剪,使用视图变换(view transform)对照相机和所有模型进行变换。 视图变换的目的是将相机放置在原点并将其对准目标,使其沿负z轴的方向看,y轴指向上方,x轴指向右侧。 应用视图变换后的实际位置和方向取决于基础应用程序编程接口(API)。这样划定的空间称为相机空间,或更常见的是眼睛空间。 视图转换影响相机和模型的方式示例如图2.4所示。 模型变换和视图变换都实现为4x4个矩阵,这是第4章的主题。
图2.4 在左图中,相机的位置和方向如用户所愿。 视图转换将相机沿负z轴重新定位在原点,如右图所示。 这样做是为了使剪切和投影操作更简单,更快捷。 浅灰色区域是视图体积。 在此,假定透视图,因为视图体积为平截头体。 类似的技术适用于任何类型的投影。

2.3.2 顶点着色

要产生逼真的场景,仅渲染对象的形状和位置是不够的,但是还必须对它们的外观进行建模。 此描述包括每个对象的材料,以及任何光源照在对象上的效果。 材质和灯光可以采用多种方式建模,从简单的颜色到物理描述的详尽表示。确定光线对材料的影响的这种操作称为阴影(shading)。 它涉及计算对象上各个点的着色方程式(shading equation)。 通常,这些计算中的一些是在几何阶段在模型顶点上执行的,而其他一些则可以在逐像素栅格化期间执行。 可以在每个顶点处存储各种材质数据,例如点的位置,法线,颜色或计算阴影方程式所需的任何其他数字信息。 然后将顶点着色结果(可以是颜色,矢量,纹理坐标或任何其他种类的着色数据)发送到栅格化阶段进行插值。阴影计算通常被认为是在世界空间中发生的。 实际上,有时将相关实体(例如相机和光源)转换到某个其他空间(例如模型或眼睛空间)并在那里执行计算很方便。 之所以可行,是因为如果将阴影计算中包括的所有实体都转换到相同的空间,则会保留光源,相机和模型之间的相对关系。着色在本书中有更深入的讨论,特别是在第3章和第5章。

2.3.3 投影

在着色之后,渲染系统执行投影(projection),它将视图体转换为一个单元立方体,其极值点位于(1,1,1)和(1,1,1)。单元立方体称为标准视图体积(canonical view volume)。有两种常用的投影方法,即正投影(orthographic)(又称平行投影(parallel))和透视(perspective)投影。参见图2.5。
图2.5 正投影,左,透视投影,右
正交视图的视图体积通常是一个矩形框,而正交投影会将此视图体积转换为单位立方体。 正射投影的主要特征是,平行线在变换后保持平行。 此转换是平移和缩放的组合。透视投影有点复杂。 在这种类型的投影中,物体离相机越远,投影后出现的越小。 此外,平行线可能会聚在地平线上。 因此,透视变换模仿了我们感知物体尺寸的方式。 从几何学上讲,视场称为视锥(frustum),是具有矩形底面的截顶金字塔。 视锥也将转换为单位立方体。 正交变换和透视变换都可以使用4x4个矩阵构造(请参见第4章),在这两种变换之后,这些模型被称为归一化的设备坐标(normalized device coordinates)中。尽管这些矩阵将一个体积转换为另一个体积,但它们被称为投影,因为在显示之后,z坐标不会存储在生成的图像中。这样,模型就可以从三维投影到二维。

2.3.4 剪贴纹理

仅将全部或部分位于视图体积内的图元传递到光栅化器阶段,然后将其绘制在屏幕上。完全位于视图体积内的图元将原样传递到下一个阶段。完全不在视图体积之外的基元不会进一步传递,因为它们不会被渲染。只是需要部分裁剪(clipping)的部分视图区域内的图元。例如,在视图体积中有一个顶点在外部且在视图体积内的一条线应相对于视图体积剪裁,以便将位于该线和视图体积的交点处的新顶点替换为外部顶点。 。投影矩阵的使用意味着将变换后的图元剪裁在单位立方体上。在裁剪之前执行视图转换和投影的优点是使裁剪问题一致。基本体总是被裁剪在单位立方体上。裁剪过程如图2.6所示。除了视图体积的六个剪切平面之外,用户还可以定义其他剪切平面以可视方式剪切对象。在第646页的图14.1中显示了显示这种可视化形式的图像,该图像称为“截面”(sectioning)。与通常由可编程处理单元执行的先前几何图形阶段不同,剪切阶段(以及后续的屏幕映射阶段)通常是由固定操作硬件处理。图2.6 投影变换后,仅需要单位多维数据集内的图元(对应于视锥中的图元)即可进行后续处理。 因此,将丢弃单位多维数据集外部的图元,并保留整个内部的图元。 与单位立方体相交的基元被裁剪到单位立方体上,从而生成新的顶点,而丢弃旧的顶点。

2.3.5 屏幕映射

只有视图体积内的(剪切)图元传递到屏幕映射阶段,并且进入该阶段时坐标仍然是三维的。 每个图元的x坐标和y坐标都将转换为屏幕坐标(screen coordinates)。 屏幕坐标和z坐标也称为窗口坐标(window coordinates)。 假定场景应渲染到窗口中,最小角在(x1,y1)处,最大角在(x2,y2),其中x1 <x2并且y1 <y2。 然后,屏幕映射是平移,随后是缩放操作。 z轴不受此映射的影响。 新的x和y坐标被称为屏幕坐标。 这些与z坐标(-1≤ z≤ 1)一起传递到光栅化台。 屏幕映射过程如图2.7所示。
图2.7 投影变换后,图元位于单位立方体中,并且屏幕映射过程会在屏幕上查找坐标。
混淆的根源是整数和浮点值与像素(和纹理)坐标的关系。 DirectX 9及其以前的版本使用坐标系,其中0.0是像素的中心,这意味着像素范围[0,9]覆盖了[-0.5,9.5)的跨度。 Heckbert [520]提出了一个逻辑上更一致的方案。 给定水平像素阵列并使用笛卡尔坐标,最左像素的左边缘在浮点坐标中为0.0。 OpenGL一直使用此方案,DirectX 10及其后续版本使用它。 该像素的中心为0.5。 因此,像素[0,9]的范围覆盖了[0.0,10.0)的范围。 转换很简单
d = f l o o r ( c ) d = floor(c) d=floor(c) (2.1)
c = d + 0.5 c=d+0.5 c=d+0.5 (2.2)
其中d是像素的离散(整数)索引,c是像素内的连续(浮点)值。
尽管所有API的像素位置值都从左到右增加,但在某些情况下OpenGL和DirectX之间的上下边缘零位置不一致。OpenGL始终支持笛卡尔系统,将左下角视为 值最低的元素,而DirectX有时会根据上下文将左上角定义为此元素。 每个问题都有其逻辑,在不同之处没有正确答案。 例如,(0,0)位于OpenGL中图像的左下角,而在DirectX中位于左上角。 DirectX的原因是屏幕上出现了许多现象,从上到下都是这样:Microsoft Windows使用此坐标系,我们以此方向读取,并且许多图像文件格式都以此方式存储其缓冲区。关键的一点是,差异是存在的,并且在从一种API迁移到另一种API时必须加以考虑。

2.4 光栅化程序阶段

给定经过变换和投影的顶点及其关联的着色数据(全部来自几何图形阶段),光栅化程序阶段的目标是计算和设置对象覆盖的像素的颜色。 此过程称为光栅化(rasterization)或扫描转换(scan conversion),因此是从屏幕空间中每个具有z值(深度值)的二维顶点以及与每个顶点关联的各种着色信息到屏幕像素的转换。与几何阶段相似,该阶段分为几个功能阶段:三角形设置,三角形遍历,像素着色和合并(图2.8)。
图2.8 光栅化阶段细分为一系列功能阶段。

2.4.1 三角形设置

在这一阶段,计算三角形表面的微分和其他数据。 此数据用于扫描转换,以及用于内插由几何图形平台产生的各种阴影数据。 此过程由专用于此任务的固定操作硬件执行。

2.4.2 三角形遍历

在此检查其中心(或样本)被三角形覆盖的每个像素,并为与三角形重叠的像素部分生成片段(fragment)。 查找哪些样本或像素在三角形内通常被称为三角形遍历(triangle traversal)或扫描转换(scan conversion)。 每个三角形片段的属性都是使用在三个三角形顶点之间插值的数据生成的(请参见第5章)。 这些属性包括片段的深度,以及来自几何图形阶段的任何阴影数据。 Akeley和Jermoluk [7]和Rogers [1077]提供了有关三角形遍历的更多信息。

2.4.3 像素底纹(Pixel Shading)

使用插值的阴影数据作为输入,此处可以执行任何每个像素的阴影计算。 最终结果是一种或多种颜色将传递到下一个阶段。 与通常由专用的硬连线硅执行的三角形设置和遍历阶段不同,像素着色阶段由可编程GPU内核执行。 这里可以使用多种技术,其中最重要的一种是纹理化(texturing)。 第6章将更详细地讨论纹理化。简单地说,对对象进行纹理化意味着将图像粘贴到该对象上。 此过程如图2.9所示。 图像可以是一维,二维或三维图像,其中二维图像是最常见的。
图2.9 左上方显示了没有纹理的龙模型。 图像纹理中的片段被粘贴到龙上,结果显示在左下方。

2.4.4 融合(Merging)

每个像素的信息都存储在颜色缓冲区(color buffer)中,颜色缓冲区是颜色的矩形阵列(每种颜色的红色,绿色和蓝色分量)。 合并阶段负责将着色阶段产生的片段颜色与当前存储在缓冲区中的颜色进行合并。 与着色阶段不同,通常执行此阶段的GPU子单元不是完全可编程的。 但是,它是高度可配置的,可实现各种效果。
此阶段还负责解决可见性。这意味着在渲染整个场景后,颜色缓冲区应包含场景中从相机的角度可见的图元的颜色。对于大多数图形硬件,这是通过Z缓冲区(也称为深度缓冲区(depth buffer))算法完成的[162]。Z缓冲区的大小和形状与颜色缓冲区相同,并且对于每个像素,它都存储z值从相机到当前最接近的图元。这意味着,当将图元渲染到某个像素时,该图元在该像素处的z值将被计算并与同一像素处Z缓冲的内容进行比较。如果新的z值小于Z缓冲区中的z值,则正在渲染的图元比之前在那个像素处最接近相机的图元更接近相机。因此,该像素的z值和颜色将使用所绘制图元的z值和颜色进行更新。如果计算的z值大于Z缓冲区中的z值,则保持颜色缓冲区和Z缓冲区不变。 Z缓冲区算法非常简单,具有O(n)收敛(其中n是要渲染的图元的数量),并且适用于任何可以为每个(相关)像素计算z值的绘图图元。还要注意,该算法允许大多数原语以任何顺序呈现,这是其普及的另一个原因。但是,部分透明的图元不能以任何顺序呈现。必须在所有不透明基元之后并以从后到前的顺序渲染它们(第5.7节)。这是Z缓冲区的主要缺点之一。
我们已经提到了颜色缓冲区用于存储颜色,Z缓冲区用于存储每个像素的z值。 但是,还有其他通道和缓冲区可用于筛选和捕获片段信息。 Alpha通道(alpha channel)与颜色缓冲区关联,并为每个像素存储相关的不透明度值(第5.7节)。 在执行深度测试之前,可以对传入的片段执行可选的alpha测试(alpha test)。 通过某些指定的测试(等于,大于等)将片段的alpha值与参考值进行比较。 如果片段未通过测试,则将其从进一步处理中删除。 该测试通常用于确保完全透明的片段不会影响Z缓冲区(请参见6.6节)。
模板缓冲区(stencil buffer)是一个屏幕外缓冲区,用于记录渲染图元的位置。 它通常每个像素包含八位。 可以使用各种功能将基元渲染到模板缓冲区中,然后可以使用缓冲区的内容来控制渲染到颜色缓冲区和Z缓冲区中。 例如,假设已将填充圆绘制到模板缓冲区中。 可以将其与允许仅在存在圆圈的情况下将后续图元渲染到颜色缓冲区中的运算符组合。 模板缓冲区是生成特殊效果的强大工具。 流水线末端的所有这些功能都称为栅格操作(raster operations ,ROP)或混合操作(blend operations)。
帧缓冲区(frame buffer)通常由系统上的所有缓冲区组成,但有时仅表示颜色缓冲区和Z缓冲区为一组。 1990年,Haeberli和Akeley [474]提出了对帧缓冲区的另一种补充,称为累积缓冲区(accumulation buffer)。 在此缓冲区中,可以使用一组运算符来累积图像。 例如,可以对示出运动中的物体的一组图像进行累积和平均以生成运动模糊。 可以生成的其他效果包括景深,抗锯齿,柔和阴影等。
当图元到达并通过光栅化器阶段时,从相机的角度可见的图元将显示在屏幕上。 屏幕显示颜色缓冲区的内容。 为了避免让人类观看者在对其进行栅格化并将其发送到屏幕时看到它们,使用了双重缓冲(double buffering)。 这意味着场景的渲染发生在屏幕后方的缓冲区中。 将场景渲染到后缓冲区中后,后缓冲区(back buffer)的内容将与先前在屏幕上显示的前缓冲区(front buffer)的内容交换。 交换发生在垂直回扫(vertical retrace)过程中,这是安全的时间。
有关不同缓冲区和缓冲方法的更多信息,请参见第5.6.2节和第18.1节。

2.5 通过管道(Through the Pipeline)

点,线和三角形是用于构建模型或对象的渲染图元。 假设该应用程序是交互式计算机辅助设计(computer aided design,CAD)应用程序,并且用户正在检查手机的设计。 在这里,我们将在整个图形渲染管道中遵循此模型,包括三个主要阶段:应用程序,几何图形和光栅化器。 通过透视图将场景渲染到屏幕上的窗口中。 在这个简单的示例中,手机模型既包含线条(以显示零件的边缘),也包含三角形(以显示表面)。 一些三角形由二维图像进行纹理处理,以表示键盘和屏幕。 对于此示例,除了在光栅化阶段发生的纹理应用之外,着色是在几何阶段完全计算的。

应用程序(Application)

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

几何结构(Geometry)

视图转换是在应用程序阶段进行计算的,并为每个对象指定了其位置和方向的模型矩阵。对于传递到几何图形阶段的每个对象,通常将这两个矩阵相乘在一起成为一个矩阵。在几何阶段,对象的顶点和法线使用此级联矩阵进行变换,从而将对象置于眼睛空间中。然后,使用材质和光源属性计算顶点处的阴影。然后执行投影,将对象转换为代表眼睛所见的单位立方空间。多维数据集外部的所有基元都将被丢弃。将与该单位多维数据集相交的所有图元都裁剪到该多维数据集上,以便获得一组完全位于单位多维数据集内的图元。然后将这些顶点映射到屏幕上的窗口中。在完成所有这些基于多边形的操作之后,将所得数据传递到流水线中最后一个主要阶段的栅格化器。

光栅化程序(Rasterizer)

在此阶段,所有图元都被光栅化,即转换为窗口中的像素。 每个对象中的每个可见线和三角形都会在屏幕空间中进入光栅化器,准备进行转换。 已将与纹理关联的那些三角形应用了该纹理(图像)进行渲染。 可见性通过Z缓冲区算法以及可选的alpha和模板测试来解决。 依次处理每个对象,然后将最终图像显示在屏幕上。

总结

该管道源于针对实时渲染应用程序的数十年的API和图形硬件演变。 重要的是要注意,这不是唯一可能的渲染管道。 离线渲染管道经历了不同的演变路径。 电影制作的渲染最常见的是使用微多边形(micropolygon)管道[196,1236]。 学术研究和预测性渲染(predictive rendering)应用程序(例如建筑预可视化)通常采用光线跟踪(ray tracing)渲染器(请参阅第9.8.2节)。
多年来,应用程序开发人员使用此处描述的过程的唯一方法是通过使用中的图形API定义的固定功能管道。 固定功能管道之所以如此命名,是因为实现它的图形硬件包含无法灵活编程的元素。 流水线的各个部分可以设置为不同的状态,例如可以打开或关闭Z缓冲区测试,但是无法编写程序来控制在各个阶段应用功能的顺序。 固定功能机器的最新(也是最后一个)示例是Nintendo的Wii。 可编程GPU使得可以准确确定在整个管道的各个子阶段中应用了哪些操作。虽然研究固定功能管道可以合理地介绍一些基本原理,但大多数新开发都针对可编程GPU。 这种可编程性是本书第三版的默认假设,因为这是充分利用GPU的现代方式。

Further Reading and Resources

Blinn的书《A Trip Down the Graphics Pipeline》 [105]是一本关于从头开始编写软件渲染器的老书,但是对于学习实现渲染流水线的一些精妙之处来说,它是一个很好的资源。 对于固定功能管道,古老的(至今仍经常更新)《OpenGL Programming Guide》(又名红皮书)[969]提供了对固定功能管道及其使用相关算法的详尽描述。 我们本书的网站http://www.realtimerendering.com提供了各种渲染引擎实现的链接。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值