NoiseFloor 发表于 2022-7-11 15:00

Chapter-2 图形渲染管线

本章介绍了实时图形的核心组件,即图形渲染管线,也简称为“管线”。管线的主要功能是将给定的一个虚拟摄像机,三维物体,光源和其他的东西,产生或者渲染成一张二维的图片。因此,渲染管线是实时渲染的基础工具。使用该管线的过程如图2.1所示。图像中物体的位置和形状由它们的几何形状、环境的特征以及相机在该环境中的摆放决定。物体的外观受到材质属性、光源、纹理(应用于表面的图像)和渲染方程的影响。


    我们将解释呈现管线的不同阶段,重点是功能而不是实现。应用这些阶段的相关细节将在后面的章节中讨论。
2.1 架构
在现实世界中,管线概念以多种不同的形式表现出来,从工厂流水线到快餐厨房。它也适用于图形渲染。流水线由几个阶段组成,每个阶段执行一个更大任务的一部分。
流水线的各个阶段并行执行,每个阶段都依赖于前一阶段的结果。理想情况下,一个非流水线的系统被分成n个流水线的阶段,它的速度可以提高到n倍。性能的提高是使用流水线的主要原因。例如,大量的三明治可以由一系列的人快速准备——一个人准备面包,另一个人加肉,另一个人加配料。每个人将结果传递给排队的下一个人,然后立即开始制作下一个三明治。如果每个人花20秒来完成他们的任务,那么每20秒一个三明治的最大速度,即每分钟三个三明治,是可能的。流水线的各个阶段是并行执行的,但是在最慢的阶段完成其任务之前,它们会被暂停。例如,肉类添加阶段变得更加复杂,需要30秒。现在能达到的最佳速度是每分钟两个三明治。对于这个特殊的管道,肉类阶段是瓶颈,因为它决定了整个生产的速度。加配料阶段(和顾客一样)在等待肉类阶段完成的过程中是饥饿的(闲置的)。
在实时计算机图形学的架构中,也可以发现这种流水线的结构。如图2.2所示,将实时渲染流水线粗略划分为四个主要阶段——程序,几何处理,光栅化和像素处理。这个结构是渲染管线引擎的核心,他用于实时计算机图形应用中,因此是后续章节讨论的重要基础。每个阶段本身通常是一个管线,这意味着它由几个子阶段组成。我们将这里显示的功能阶段和它们的实现结构加以区分。功能阶段有一个特定的任务要执行,但不指定该任务在流水线中执行的方式。一个给定的实现可以将两个功能阶段组合成一个单元或使用可编程核执行,而它将另一个更耗时的功能阶段分割成几个硬件单元。


渲染速度可以用帧每秒(FPS)表示,即每秒渲染的图像数量。它也可以用赫兹(Hz)表示,这是 1/seconds 的简单符号,也就是更新的频率。通常还可以用毫秒(ms)表示渲染图像所需的时间。生成图像的时间通常是不同的,这取决于每帧计算的复杂性。FPS用来表示特定帧的速率,或者在使用期间的平均性能。赫兹用于硬件,如显示器,它被设置为固定速率。
顾名思义,应用程序阶段由应用程序驱动,因此通常在运行在通用cpu上的软件中实现。这些cpu通常包括多个核,这些核能够处理并行执行多个线程。这使得cpu能够有效地运行应用程序阶段负责的大量任务。一些传统上在CPU上执行的任务包括碰撞检测、全局加速算法、动画、物理模拟等,这取决于应用程序的类型。下一个主要阶段是几何处理,它处理转换、投影和所有其他类型的几何操作。这个阶段计算要绘制什么,如何绘制,以及在哪里绘制。几何阶段通常在图形处理单元(GPU)上执行,它包含许多可编程内核以及固定操作硬件。光栅化阶段通常采用三个顶点作为输入,形成一个三角形,并查找该三角形内的所有像素,然后将这些像素转发到下一阶段。最后,像素处理阶段对每个像素执行一个程序,以确定它的颜色,并可以执行深度测试,以查看它是否可见。它还可以执行逐像素操作,例如将新计算的颜色与以前的颜色混合。栅格化和像素处理阶段也完全在GPU上进行。所有这些阶段及其内部管线将在接下来的四个部分中进行讨论。第3章更详细地介绍了GPU处理这些阶段的内容。
2.2 程序阶段
开发人员可以完全控制应用程序阶段发生的事情,因为它通常是在CPU上执行的。因此,开发人员可以完全决定实现方法,并可以稍后修改它以提高性能。这里的更改还会影响后续阶段的性能。因此程序阶段的算法或设置能减少被渲染三角形的数量。
这就是说,通过使用独立的计算着色器的方法,一些程序阶段的工作可以通过GPU完成。这种模式将GPU视为一个高度并行的通用处理器,忽略了其特殊的用于渲染图形的功能。
在应用阶段的最后,要渲染的几何图形被提交到几何处理阶段。这些是渲染图元,即点、线和三角形,它们最终可能出现在屏幕上(或任何正在使用的输出设备)。这是应用阶段最重要的任务。
基于软件实现这一阶段的结果是,它没有像几何处理、光栅化和像素处理阶段那样划分为子阶段。然而,为了提高性能,这个阶段通常在几个处理器核心上并行执行。在CPU设计中,这被称为超标量的构造,因为它能够在同一阶段同时执行多个进程。第18.5节介绍了使用多处理器核心的各种方法。
在这个阶段通常实现的一个过程是碰撞检测。在检测到两个物体之间的碰撞后,可以生成响应,并发送回碰撞物体和力反馈装置。应用程序阶段也是处理来自其他来源(如键盘、鼠标或头戴式显示器)的输入的地方。根据这个输入,要采取几种不同类型的操作。加速算法,例如特定的剔除算法(第19章),也在这里实现,还有管线的其他部分不能处理的也在这里实现。
2.3 几何处理
GPU上的几何处理阶段负责大多数逐三角形和逐顶点的操作。这个阶段进一步分为以下功能阶段:顶点着色器,投影,裁剪和屏幕映射(图2.3)。


2.3.1 顶点着色
顶点着色有两个主要任务,即计算顶点的位置和计算程序员可能想要的任何顶点输出数据,比如法线坐标和纹理坐标。传统上,一个物体的大部分颜色都是通过对每个顶点的位置应用光照和法线来计算的,只存储顶点的结果颜色。然后这些颜色通过插值得到三角形内的其他点的颜色。因此,这个可编程的顶点处理单元被命名为顶点着色器。随着现代GPU的出现,以及部分或全部的着色发生在每个像素上,这使顶点着色阶段更加普遍地可能不会计算任何着色方程,这取决于程序员的意图。顶点着色器现在是一个更通用的单元,专门用于设置与每个顶点相关的数据。例如,顶点着色器可以使用章节4.4和4.5中的方法来使一个对象动起来。
我们从描述如何计算顶点位置开始,这总是需要一组坐标。在进入屏幕的过程中,模型被转换到几个不同的空间或坐标系统。最初,模型驻留在它自己的模型空间中,这意味着它根本没有被转换。每个模型都可以与一个模型转换相关联,这样它就可以被定位和定向。可以有几个模型转换与一个模型相关联。这允许同一个模型的多个副本(称为实例)在同一个场景中具有不同的位置、方向和大小,而不需要复制基本的几何图形(可以想象一个汽车,内部有轮胎,方向盘,雨刮器等,通过复制好几个汽车实例放置在不同的位置和方向,再叠加上汽车自己的内部模型转换就得到不同的方向盘在世界场景中的位置,而不需要设置多个世界场景中的方向盘的位置)。
模型变换所转换的是模型的顶点和法线。对象的坐标称为模型坐标,在对这些坐标进行了模型转换之后,就得到了该模型位于世界坐标系或世界空间中的坐标。世界空间是唯一的,在模型通过各自的模型转换后,所有的模型都存在于这个相同的空间中。
如前所述,只有摄像机(或观察者)看到的模型才会被渲染。相机在世界空间中有一个位置和一个方向,用来放置和瞄准相机。为了便于投影和裁剪,相机和所有的模型都用视图变换进行了转换。视图变换的目的是将摄像机放置在原点并瞄准它,让它朝负z轴方向看,y轴指向上方,x轴指向右侧。我们使用z轴约定;有些章倾向于看向+z轴。区别主要是语义上的,因为两者之间的转换很简单。应用视图转换后的实际位置和方向取决于底层应用程序编程接口(API)。这样描述的空间被称为相机空间,或者更一般的,视图空间或眼睛空间。视图变换影响相机和模型的一个例子显示在图2.4。模型转换和视图转换都可以实现为4×4矩阵,这是第四章的主题。然而,重要的是要认识到,顶点的位置和法线可以用程序员喜欢的任何方式计算得到。


接下来,我们描述顶点着色输出的第二种类型。要制作逼真的场景,仅仅渲染物体的形状和位置是不够的,还必须对它们的外观建模。这个描述包括每个物体的材质,以及任何光源照射在物体上的效果。材质和灯光可以以任何方式建模,从简单的颜色到物理描述的复杂表示。
这种确定光线在材质上的效果的操作称为着色。它涉及到计算物体上不同点的着色方程。通常,其中一些计算是在模型顶点的几何处理期间执行的,其他的可能是在逐像素处理期间执行的。各种材质数据可以存储在每个顶点上,比如点的位置、法线、颜色或任何其他计算着色方程所需的数值信息。顶点着色结果(可以是颜色,向量,纹理坐标,以及任何其他类型的着色数据)然后被发送到光栅化和像素处理阶段,进行插值,并用于计算表面的着色。
GPU顶点着色器形式的顶点着色在本书中有更深入的讨论,特别是在第3章和第5章。
作为顶点着色的一部分,渲染系统执行投影和裁剪,这将视锥体转换为一个端点在(1,1,1)和(1,1,1)的单位立方体。可以使用定义相同体积的不同范围,例如0≤z≤1。单位立方体称为正规化可视空间。投影是首先完成的,在GPU上是由顶点着色器完成的。常用的投影方法有两种,即正交投影(也称平行投影)和透视投影。见图2.5。事实上,正交投影只是平行投影的一种类型。其他一些方法也得到了应用,特别是在建筑领域,如斜投影和轴测投影。老街机游戏《Zaxxon》就是从后者得名的。


请注意,投影表示为一个矩阵(第4.7节),因此有时它可能与几何变换的其余部分连接在一起。
正交投影视图的视图体积通常是一个矩形框,正投影将这个视图体积转换成单位立方体。正交投影的主要特点是变换后平行线保持平行。这种转换是平移和缩放的结合(将正交投影的视区域通过平移和缩放可以转换为一个单位立方体,立方体中心在原点)。
透视投影有点复杂。在这种类型的投影中,一个物体离相机越远,它在投影后看起来就越小。此外,平行线可能在地平线处相交。因此,透视变换模仿了我们感知物体大小的方式。几何上,视体,称为平截头体,是一个被矩形底截断的金字塔。平截头体同样转换成单位立方体(便于计算裁剪)。正交和透视变换都可以用4 × 4矩阵来构造(第4章),任何一个变换之后,模型都被认为是在裁剪坐标系中。这些实际上是齐次坐标,在第四章讨论,所以这发生在除以w之前。GPU的顶点着色器必须总是输出这种类型的坐标,以便下一个功能阶段,裁剪,正常工作。
尽管这些矩阵将一个体积转换成另一个,但它们被称为投影,因为在显示之后,z坐标并不存储在生成的图像中,而是存储在z缓冲区中,如在第2.5节所述。通过这种方式,模型从三维投影到二维。
2.3.2 可选的顶点处理
每个管线都有刚才描述的顶点处理过程。一旦这个处理完成,GPU上还有几个可选的阶段按这个顺序进行处理:细分、几何着色和流输出。它们的使用既取决于硬件的能力(并非所有GPU都有),也取决于程序员的需求。它们是相互独立的,平常也不常用。我们将在第三章详细介绍他们。
第一个可选的阶段是细分。假设你有一个弹跳的球。如果用一组三角形表示它,则可能会遇到质量或性能方面的问题。你的球在5米外看起来可能很好,但随着距离拉进,单独的三角形,特别是轮廓,变得可见(棱变得明显,不够圆滑)。如果你用更多的三角形来制作球来提高质量,当球离你很远并且只覆盖屏幕上几个像素时,你可能会浪费大量的处理时间和内存。使用细分,可以用适量的三角形生成一个曲面。
我们已经讨论了一点三角形,但是到目前为止,我们只处理了顶点。这些可以用来表示点、线、三角形或其他对象。顶点可以用来描述曲面,比如一个球。这样的表面可以由一系列顶点组成的块指定。细分阶段本身包括一系列的阶段——外壳着色器、曲面细分器和域细分器——这些阶段将这些块顶点集转换成(通常)更大的顶点集,然后用于生成新的三角形集。场景的摄像机可以用来确定生成多少三角形:当块接近时,会生成很多三角形,而当块远离时,则生成很少三角形。
下一个可选的阶段是几何着色器。这个着色器先于细分着色器,所以在gpu上更常见。它就像细分着色器,它接受各种各样的图元,并可以产生新的顶点。这是一个简单得多的阶段,因为创建的范围有限,输出图元的类型也很有限。几何着色器有几个用途,其中最流行的是粒子生成。想象一下模拟烟花爆炸。每个火球都可以用一个点,一个单独的顶点表示。几何着色器可以将每个点变成一个正方形(由两个三角形组成),面向视口并覆盖几个像素,因此为我们提供了一个更有说服力的图元用于着色。
最后一个可选的阶段叫做流输出。在这个阶段,我们可以将GPU用作几何引擎。在这一点上,我们可以选择将这些顶点输出到一个数组以进行进一步处理,而不是将我们处理过的顶点发送到管线的剩余部分以呈现在屏幕上。这些数据可以被CPU使用,也可以被GPU本身使用。这个阶段通常用于粒子模拟,例如我们的烟火例子。
这三个阶段是按顺序执行的——细分、几何着色和流输出——而且每个阶段都是可选的。不管使用哪个阶段(如果有的话),如果我们继续沿着管线走下去,我们就会得到一组齐次坐标的顶点,我们将检查摄像机是否能看到它们。
2.3.3 裁剪
只有视景体内部的全部或部分的图元需要被传递到光栅化阶段(以及随后的像素处理阶段),然后在屏幕上绘制它们。一个完全位于视景体内的图元将被传递到下一个阶段。完全在视景体之外的图元不会被进一步传递,因为它们不会被渲染。需要被裁剪的是部分位于视景体内部的图元。例如,一条有一个顶点在视景体外部,一个顶点在视景体内部的线应该被视景体裁剪,这样外部的顶点就会被一个位于线和视景体之间的交点的新顶点所取代。投影矩阵的使用意味着变换后的图元会被单位立方体裁剪。在裁剪之前执行视图转换和投影的优点是,它使裁剪问题保持一致:图元总是被单元立方体裁剪。
裁剪过程如图2.6所示。除了视景体的六个剪切平面外,用户还可以定义额外的剪切平面以可见地切割对象。这种类型的可视化的图像(称为切片)如818页的图19.1所示。


裁剪步骤使用由投影产生的4值齐次坐标来执行裁剪。值通常不会在透视空间中跨三角形线性插值。第四个坐标是必需的,以便在使用透视投影时正确地插值和裁剪数据。最后,执行透视除法,将得到的三角形位置置于三维规范化的设备坐标中。如前所述,此视景体的范围为(1,1,1)到(1,1,1)。几何阶段的最后一步是从这个空间转换到窗口坐标系。
2.3.4 屏幕映射
只有视景体内的(剪切的)图元被传递到屏幕映射阶段,当进入这个阶段时,坐标仍然是三维的。每个图元的x和y坐标被转换成屏幕坐标。屏幕坐标和z坐标也称为窗口坐标系。假设场景应该呈现在一个窗口中,最小角在(x1, y1),最大角在(x2, y2),其中x1 < x2, y1 < y2。然后屏幕映射是平移加缩放操作。新的x-和y坐标被称为屏幕坐标。z坐标(OpenGL的和DirectX的)也映射到, z1 = 0和z2 = 1作为默认值。但是,这些可以用API更改。窗口坐标和这个映射的z值被传递到光栅化阶段。屏幕映射过程如图2.7所示。


接下来,我们将描述整数和浮点值如何与像素(和纹理坐标)联系起来的。给定一个水平像素数组并使用笛卡尔坐标,最左边像素的左边缘在浮点坐标中是0.0。OpenGL一直使用这种方案,并且DirectX 10和它的后续版本也使用它。这个像素的中心是0.5。因此,像素范围覆盖了从[0.0,10.0)开始的跨度。转换很简单。


其中d是像素的离散(整数)索引,c是像素内的连续(浮点)值。
虽然所有api都有从左到右增加的像素位置值,但在某些情况下,顶部或者底部边缘是零位置是不一致的在OpenGL和DirectX之间。OpenGL始终支持笛卡尔系统,将左下角作为值最低的位置,而DirectX取决于上下文有时将左上角定义为这个位置。每一个都有其逻辑,它们的不同之处不存在正确答案。例如,(0,0)在OpenGL中位于图像的左下角,而在DirectX中位于左上角。当从一个API迁移到另一个API时,这个差异是很重要的。
2.4 光栅化
p data-pid="rwYlXSsN">给定转换后的和投影的顶点及其相关的着色数据(都来自于几何处理),下一阶段的目标是找到在被渲染的图元中的所有的像素——图片元素的缩写,例如,一个三角形。我们称这个过程为光栅化,它分为两个功能子阶段:三角形设置(也称为图元装配)和三角形遍历。这些如图2.8的左侧所示。注意,这些阶段也可以处理点和线,但是因为三角形是最常见的,所以子阶段的名称中有“三角形”。光栅化,也称为扫描转换,是将屏幕空间中的二维顶点(每个顶点都有一个z值(深度值)和与每个顶点相关的各种着色信息)转换为屏幕上的像素。光栅化也可以被认为是几何处理和像素处理之间的同步点,因为三角形是在这里由三个顶点形成的,并最终发送到像素处理。</p>

三角形是否被认为与像素重叠取决于你如何设置GPU的管线。比如你可以使用点采样来决定是否在三角形内部。最简单的情况是在每个像素的中心使用一个单点样本,所以如果中心点在三角形内,那么对应的像素也被认为在三角形内。你也可以使用超采样或多重采样抗锯齿技术(章节5.4.2)在每个像素上使用多个采样。另一种方法是使用传统的光栅化,其定义是,如果至少有一部分像素与三角形重叠,则该像素是“在”三角形内。
2.4.1 三角形建立
在这一阶段,微分、边方程和三角形的其他数据被计算出来。这些数据以及插值的在几何阶段产生的各种着色数据,可用于三角形遍历。固定功能硬件用于完成这项任务。
2.4.2 三角形遍历
在这里,三角形检测覆盖其中心点的每个像素,并为部分重叠三角形的像素生成一个片元。更详细的采样方法见章节5.4。查找哪些样本或像素在一个三角形内通常称为三角形遍历。每个三角形片段的属性是通过在三个三角形顶点之间插值数据生成的(第五章)。这些属性包括片元的深度,以及任何来自几何阶段的着色数据。McCormack等人提供了更多关于三角形遍历的信息。在这里,在三角形上执行透视校正插值。所有在图元中的像素或样本随后被发送到像素处理阶段,接下来会描述。
2.5 像素处理
在这时,所有被认为在三角形或其他图元中的像素都已经被发现,这是所有之前阶段的结果。像素处理阶段分为像素着色和像素合并,如图2.8中所示。像素处理是对图元内的像素或样本进行逐像素或逐样本计算和操作的阶段。
2.5.1 像素着色
任何逐像素着色计算都在这里执行,使用插值的着色数据作为输入。最终的结果是一个或多个颜色被传递到下一个阶段。不像三角形设置和遍历阶段,通常是由固定功能管线操作,像素着色阶段是可编程的。为此,程序员为像素着色器(或片段着色器,在OpenGL中称为片段着色器)提供了一个程序,它可以包含任何想要的计算。这里可以使用各种各样的技术,其中最重要的是纹理。纹理将在第6章中进行更详细的处理。简单地说,对一个对象进行纹理化意味着为了各种目的,将一个或多个图像“粘”到该对象上。图2.9描述了这个过程的一个简单示例。图像可以是一维、二维或三维的,其中二维图像最常见。在最简单的情况下,最终产品是每个片段的颜色值,这些被传递到下一个子阶段。


2.5.2 混合
每个像素的信息存储在颜色缓冲中,颜色缓冲是一个矩形的颜色数组(每种颜色分别有红色、绿色和蓝色组件)。合并阶段负责将像素着色阶段产生的片段颜色与当前存储在缓冲区中的颜色结合起来。这个阶段也被称为ROP,代表“光栅操作(管线)”或“渲染输出单元”,这取决于你问哪一个。不同于着色阶段,执行这一阶段的GPU子单元通常不是完全可编程的。但是,它是高度可配置的,可以实现各种效果。
这个阶段还负责解决可见性问题。这意味着当整个场景被渲染后,颜色缓冲应该包含场景中从摄像机角度可见的基本图元的颜色。对于大多数甚至所有的图形硬件,这是通过z缓冲区(也称为深度缓冲区)算法完成的。缓冲区的大小和形状与颜色缓冲区相同,对于每个像素,它存储了当前最接近的图元的z值。这意味着,当一个图元被渲染到某个像素时,将计算该像素上图元的z值,并将其与相同像素上z缓冲区的内容进行比较。如果新的z值小于z缓冲区中的z值,那么正在渲染的图元比之前在该像素上最接近摄像机的图元更接近摄像机。因此,该像素的z值和颜色将使用正在绘制的图元的z值和颜色进行更新。如果计算的z值大于z缓冲区中的z值,那么颜色缓冲区和z缓冲区将保持原样。z缓冲区算法很简单,有O(n)收敛(其中n是被渲染的图元的数量),适用于任何可以为每个(相关)像素计算z值的绘图图元。还要注意,该算法允许以任何顺序呈现大多数图元,这是它流行的另一个原因。然而,z缓冲区在屏幕上的每个点只存储一个深度,所以它不能用于半透明的图元。这些必须在所有不透明的图元之后渲染,并按前后顺序渲染,或者使用独立于顺序的算法。透明度是基本z缓冲区的主要弱点之一。
我们已经提到过,颜色缓冲区用于存储颜色,而z缓冲区用于存储每个像素的z值。然而,还有其他通道和缓冲区可以用来过滤和捕获片段信息。alpha通道与颜色缓冲区相关联,并为每个像素存储一个相关的不透明度值。在旧的API中,alpha通道也被用来通过alpha测试特性有选择地丢弃像素。现在,丢弃操作可以插入到像素着色程序中,任何类型的计算都可以用来触发丢弃操作。这种类型的测试可以用来确保完全透明的片段不会影响z缓冲区。
模板缓冲区是一个屏幕外的缓冲区,用于记录渲染的图元的位置。它通常每像素包含8位。可以使用各种方法将图元渲染到模板缓冲区中,模板的内容可以用于控制渲染进颜色缓冲区和深度缓冲区的内容。例如,假设一个填充的圆已经绘制到模具缓冲区中。这可以与一个操作相结合,该操作允许只在圆形出现的地方将后续的图元渲染到颜色缓冲区中。模板缓冲区可以是生成一些特殊效果的强大工具。所有这些管道末端的功能都被称为光栅操作(ROP)或混合操作。可以将颜色缓冲区中当前的颜色与三角形中正在处理的像素的颜色混合。这可以产生如透明度或积累的颜色样本等效果。如前所述,混合通常可以使用API进行配置,而不是完全可编程。然而,一些API支持光栅顺序视图,也称为像素着色顺序,它支持可编程的混合功能。
帧缓冲区通常由系统上的所有缓冲区组成。
当图元达到并通过光栅化阶段时,那些从摄像机的角度可见的图元将显示在屏幕上。屏幕显示颜色缓冲区的内容。为了避免让人类查看者在栅格化并发送到屏幕时看到图元,使用了双缓冲。这意味着场景的渲染发生在屏幕之外,在一个后台缓冲区中。一旦场景在后台缓冲区中完成渲染,后台缓冲区的内容将与之前在屏幕上显示的前台缓冲区的内容交换。交换通常发生在垂直回溯期间,此时这样做是安全的。
关于不同缓冲区和缓冲方法的更多信息,请参见第5.4.2节,23.6和23.7。
2.6 完整的管线流程
点、线和三角形是用来构建模型或对象的渲染图元。假设应用程序是一个交互式计算机辅助设计(CAD)应用程序,用户正在检查华夫饼机的设计。在这里,我们将跟随这个模型来浏览整个图形渲染流程,包括四个主要阶段:应用、几何、光栅化和像素处理。场景通过透视呈现到屏幕上的一个窗口。在这个简单的例子中,华夫饼机模型既包括线条(以显示部件的边缘),也包括三角形(显示表面)。华夫饼机有一个可以打开的盖子。一些三角形由带有制造商标识的二维图像纹理。在这个例子中,除了在栅格化阶段的纹理应用之外,表面着色是在几何阶段完成计算的。
应用
CAD应用程序允许用户选择和移动模型的部分。例如,用户可以选择盖子,然后移动鼠标来打开它。应用程序阶段必须将鼠标移动转换为相应的旋转矩阵,然后确保在渲染时将这个矩阵适当的应用到盖子上。另一个例子:动画会沿着预设的路径移动摄像机,从不同的角度展示华夫饼机。相机参数,如位置和视图方向,必须由应用程序根据时间更新。对于要渲染的每一帧,应用程序阶段将相机位置、光照和模型的图元提供给流水线中的下一个主要阶段——几何阶段。
几何处理
对于透视图,我们假设应用程序提供了一个投影矩阵。此外,对于每个对象,应用程序都计算了一个矩阵,该矩阵描述视图转换以及对象本身的位置和方向。在我们的例子中,华夫饼机的基座有一个矩阵,盖子有另一个矩阵。在几何阶段,对象的顶点和法线被这个矩阵转换,将对象放入视图空间。然后可以使用材质和光源属性在顶点处计算颜色或其他计算。然后使用一个单独的用户提供的投影矩阵来执行投影,将对象转换为代表肉眼所见的单位立方体空间。立方体外的所有图元都将被丢弃。所有与这个单元立方体相交的图元都被剪切到这个立方体上,以获得一组完全位于这个单元立方体内的图元。然后这些顶点被映射到屏幕上的窗口中。在执行所有这些每三角形和每顶点操作之后,结果数据被传递到光栅化阶段。
光栅化
所有在前一阶段的剪切中幸存下来的图元都将被光栅化,这意味着找到图元中的所有像素,并将其进一步发送到像素处理流程中。
像素处理
这里的目标是计算每个可见图元的每个像素的颜色。那些已经与任何纹理(图像)相关联的三角形将根据需要使用这些应用于它们的图像进行渲染。可见性是通过z缓冲区算法,以及可选的丢弃和模板测试来解决的。每个对象依次处理,最后的图像然后显示在屏幕上。
结论
这一管线源于数十年来针对实时渲染应用程序的API和图形硬件的发展。需要注意的是,这并不是唯一可能的呈现管道;离线渲染管道经历了不同的发展路径。用于电影制作的渲染通常使用微多边形管线来完成,但是光线追踪和路径追踪最近开始流行。这些技术在11.2.2中有介绍,也可用于建筑和设计视觉。
多年来,应用程序开发人员使用这里描述的过程的唯一方法是通过使用的图形API定义的固定功能管线。固定功能管线之所以如此命名,是因为实现它的图形硬件由无法以灵活方式编程的元素组成。最后一个大型固定功能游戏机的例子是任天堂(Nintendo)在2006年推出的Wii。可编程的GPU另一方面,可以精确地确定在整个管线的各个子阶段中应用了哪些操作。对于本书的第四版,我们假设所有的开发都是使用可编程GPU完成的。
补充阅读和在线资源
Blinn的《沿着图形管道的旅程》是一本关于从零开始编写软件渲染器的老书。这是一个很好的资源来学习一些微妙的实现渲染管道,解释关键算法,如裁剪和透视插值。值得尊敬的(但经常更新)OpenGL编程指南(又名“红宝书”)提供了与它的使用相关的图形管道和算法的详细描述。本书的网站提供了各种管线图、渲染引擎实现等链接。
页: [1]
查看完整版本: Chapter-2 图形渲染管线