现在的位置: 首页 > 综合 > 正文

实时渲染(第三版):第二章 图形渲染管道 2.2 2.3

2014年01月10日 ⁄ 综合 ⁄ 共 4073字 ⁄ 字号 评论关闭

 

2.2 应用阶段

    开发者对应用阶段发生的事物拥有完全的控制;能够完全决定实现,为提高性能在稍后修改它。此处的改变也会影响到后续阶段的性能。例如,一个应用阶段的算法或设定可以减少将被渲染的三角形的数量。

    应用阶段的最后,将被渲染的几何形状将被填充到几何形状阶段。最终显示在屏幕(或使用的其他什么输出设备)上是那些渲染基元,如点、线和三角形。这是应用阶段最重要的任务。

    这个阶段使用基于软件的实现,它的后果是阶段没有像几何形状和光栅化阶段那样,被分割成几个子阶段(因为CPU本身在一个更小的规模上管道化,你当然可以说,应用阶段被进一步分割成几个管道阶段,但这和此处无关)。不过,为了提高性能,该阶段常常在多个处理器核心上并行执行。在CPU设计中,由于它能够在相同的时间、相同的阶段执行多个处理,被称作超标构造。节15.5介绍了各种不同的利用多处理器核的方法。

    本阶段通常实现的一个处理是碰撞检测。在检测到两个对象间的碰撞后,会产生一个响应,在返回到碰撞对象的同时还会回馈到力反馈设备上。应用阶段也是处理其他来源输入(如,键盘、鼠标、头戴式头盔等)的地方。根据这些输入,需要采取几种不同的动作。本阶段实现的其他处理还有:纹理动画、转换动画,还有其他阶段无法执行的计算。加速算法,如分层视域剔除(参考第十四章),也在此阶段实现。

2.3 几何形状阶段

    几何形状阶段负责大多数逐多边形、逐顶点的操作。本阶段被进一步分割到下面的几个功能阶段:模型视图转换,顶点着色,投影,剪切和屏幕映射(图2.3)。注意,根据实现,这些功能阶段可能等价于管道阶段,也可能不会。在某些情况下,一些连续的功能阶段形成一个单独的管道阶段(它和其他管道阶段并行执行)。在另外一些情况下,一个功能阶段可能又细分为几个更小的管道阶段。


 图 2.3 几何形状阶段细分为几个功能阶段

    例如,一种极端情况,渲染管道中的所有阶段都运行于单处理器上的软件中,那么你可以说,你的整个管道由一个管道阶段组成。当然,在独立加速器芯片和加速板来临之前,这是所有图形的生成方式。另一个极端的情况,每个功能阶段细分为几个更小的管道阶段,而这些管道阶段中的每一个都运行于一个指定的处理器核。

2.3.1 模型视图转换

    在绘画到屏幕过程中,模型会被转换到几种不同的空间或坐标系中。一开始,模型处于其自身的模型空间,即是说它没有经过任何转换。每个模型都可以关联到一个模型转换,这样它才能被重新定位和指定朝向。一个模型也可以关联到多个模型转换。这允许同一个模型的多个拷贝(叫做实例)拥有不同的位置,朝向和大小,并且这些拷贝处于同一个场景,而且无需复制基础几何形状。

    模型转换转换的是模型的顶点和法线。对象的坐标叫做模型坐标,在模型转换应用到这些坐标之后,我们就说模型处在了世界坐标或世界空间。世界空间是唯一的,在模型进行模型转换之后,所有的模型将处于同一个空间。

    如前面所提,只有相机(或观察者)看到的模型才会被渲染。在世界空间中,相机有一个位置和方向。为方便投影和剪切,相机和模型会被执行视图转换。视图转换的目的是将相机放置在原点,让它面向-z轴(我们使用-z轴的约定。有一些文章会使用+z轴,它们主要是语义上不同;它们之间的转换是简单的),让y轴指向上方,x轴指向右方。视图转换之后的实际位置和方向依赖于底层应用程序接口(API)。这个划分的空间称作相机空间,更通俗地讲,叫眼睛空间。视图转换影响相机和模型的方式,它的一个示例如图2.4所示。模型转换和视图转换都被实现为4*4的矩阵,这是第四章的主题。


  图 2.4 左图中,用户指定了相机的位置和朝向。视图转换重新定位相机的位置到原点,沿着-z轴观看,,如右图所示。这么做是为了让剪切和投影操作更简单更快速。右侧灰色区域是观察体。此处,假设为透视投影。其他种类的投影可使用类似的技术。

2.3.2 顶点着色

    为产生一个真实的场景,仅仅渲染对象的形状和位置是不够的,我们还需要塑造它们的外观,包括材质,以及光源照射的效果等。材质和光照可以使用许多方式(从简单的颜色到物理描述的细致表现)塑造。

    根据材质决定光照效果的操作叫做着色。它需要对对象上的各个不同的点进行着色方程的计算。通常,这些计算中,有一些会在几何形状阶段针对模型的顶点进行,另外一些则在逐像素光栅化阶段执行。各种材质数据(如点的位置、法线、颜色,以及计算着色方程所需的其他任何数值信息)可以存储在各个顶点。顶点着色的结果(可以是颜色,向量,纹理坐标或其他任何种类的着色数据)随后被送往光栅化阶段进行插值。

    着色器计算通常在世界空间中发生。在实践中,有些时候,将相关实体(如相机和光源)转换到其他空间(如模型空间或眼睛空间)、并在该空间进行计算会比较方便。如果着色计算中用到的所有实体都被转换到同一个空间,则光源、相机和模型之间的相对关系就能够得以保留,那么转换到其他空间并在其他空间进行计算的这种方法就可以正常工作。

    本书对着色会有更加深入的讨论,尤其是第三章和第五章。

2.3.3 投影

    在着色之后,渲染系统执行投影。它转换观察体到单位立方体中,该立方体的两个极值点是(-1,-1,-1)和(1,1, l)(也可能使用不同的观察体,比如0≤z≤1。对使用其他范围,Blinn有一篇有意思的文章[102])。单位立方体称作标准观察体。常见的投影方法有两种,分别是:正视投影(也叫平行投影(实际上,正视投影只是平行投影的一种。比如,还有一种斜视平行投影方法[516],只不过使用的比较少))和透视投影,参考图2.5。

 
 图 2.5 左边是正视投影;右边是透视投影。

    正视投影的观察体通常是一个矩形框,正视投影转换该观察体到单位立方体中,正视投影的主要特性是,在转换之后,平行的线仍然是平行的。这种转换是平移和缩放的组合。

    透视投影稍微复杂点。在这种类型的投影中,对象距离相机的越远,投影后它就显得越小。另外,平行的线会相交。透视转换模仿的是我们感知对象大小的方式。在几何上,观察体被叫做平截头体,是一个截断了的、拥有矩形基的金字塔。平截头体也被转换到单位立方体。正视和透视转换都可以使用4*4的矩阵(参考第四章)构造;并且,在转换之后,我们就说模型处于标准设备坐标。

    这些矩阵将一个观察体转换到另外一个,它们被叫做投影,是因为在显示之后,z坐标不会存储在生成的图像(而是存储在z缓冲(深度缓冲)中,参考节2.4)中。在这个过程中,模型被从三维投影为2维。

2.3.4 剪切

    只有全部或部分在观察体内的基元需要被传递到光栅化阶段,光栅化阶段随后将它们绘画到屏幕。完全在观察体内的基元被原封不动地传递给下一个阶段。完全在观察体之外的基元则会舍弃,因为它们不会被渲染。只有那些部分在观察体内的基元才需要剪切。例如,一个顶点在观察体内、而另一个顶点在观察体外的线就应当根据观察体进行剪切,这样,在观察体外的顶点才能被替换为一个新的顶点,这个新的顶点是线和观察体的交点。使用投影矩阵意味着转换后的基元针对单位立方体进行了剪切。在剪切之前执行视图转换和投影的优点是它使得剪切问题一致化;基元总是针对单位立方体进行剪切。剪切过程如图2.6所示。除了观察体的6个剪切平面,用户还可以定义额外的剪切平面以显式地截去对象。这种可视化类型,叫做切片,如图14.1所示。几何形状阶段通常被可编程的处理单元执行,而剪切阶段(后面的屏幕映射阶段也是)和它不同,通常被固定操作硬件处理。


 图 2.6 在投影转换之后,只有处于单位立方体(和视锥内部的基元对应)内部的基元才需要继续处理。因此,在单位立方体之外的基元被舍弃,而完全在单位立方体之内的基元被保留;相交的基元则进行剪切,生成新的顶点,而老的被丢弃。

2.3.5 屏幕映射

    只有在观察体内部的(已剪切的)基元被传递给屏幕映射阶段,并且坐标仍然是三维的。转换其中的x和y坐标以形成屏幕坐标。屏幕坐标和z坐标一起,也叫做窗口坐标。假设场景需要被渲染到两个角为(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是像素的离散(整数)索引,c是像素内部的连续(浮点数)值。

    所有的API拥有的像素位置值,从左到右增加;但是,在一些情况下,在OpenGL和DirectX之间,表示顶部的位置0和底部边缘的位置,并不一致。OpenGL将笛卡尔坐标系贯穿始终,将左下角当作最小元素;而DirectX有时定义左上角作为最小元素(依赖于环境)。它们各自有各自的逻辑,不存在它们不同之处的正确答案。作为一个例子,(0, 0), 在OpenGL中,位于图像的左下角;而在DirectX中,它位于左上角。DirectX这么做的原因是屏幕上从上到下的一些现象:MS Windows系统使用这个坐标系统,我们按这个方向阅读,许多格式的图像文件使用这种方式存储它们的缓冲。关键的一点是,有不同存在,在从一个AIP转到另外一个时,我们需要考虑到这个不同

抱歉!评论已关闭.