几何处理阶段的职责是逐多边形和逐顶点操作,该阶段被进一步分成例如以下几个阶段:模型视图变换,顶点着色。投影,裁剪以及屏幕映射(图2.3),再次强调一下。依据实现的不同,这些功能阶段可能相当也可能不相当于管线阶段,有时几个连续的功能阶段能够合成一个管线阶段(与其他管线并行地运行)。有时一个功能管线可能被分成几个更小的管线阶段。
在极端情况下。在整个渲染管线中的全部阶段能够以软件的形式运行一下处理器上。因此也能够说整个管线仅仅包括一个管线阶段。当然这也仅仅是在独立加速芯片出现之前全部图形的生成方式。
在另外一些极端情况下,每一个功能阶段都能够被划分成几个小的管线阶段。每一个管线阶段都运行在指定的处理核心上。
2.3.1 模型与视图变换
在显示到屏幕上的过程中,一个模型会被置换到几个不同的坐标系中。最始一个模型属于它的模型空间。这也意味着在该坐标系下模型无需变换。每一个模型都能够被指定一下模型变换来指定位置和朝向。也能够给一个模型指定多个不同的变换,这使得同样模型的不同拷贝(实例)能够不复制主要的几何数据而在屏幕上具有不同的位置,朝向及尺寸。
模型变换的对象是模型的顶点和法线。一个对象的坐标系称为模型坐标系,在模型系中通用模型变换后模型被放在了世界空间或者世界坐标系,世界空间是唯一的,经过与之相关的模型变换之后。全部模型都位于同样的空间中。
就像前面提到的,仅仅能被相机(观察者)看到的模型才干够被渲染。相机在世界空间有位置与方向来放置与对准相机。为了进行投影及裁剪。相机和全部模型都被置换到视图空间。视图变换的目的是为了将相机放置在原点并对准它,来使它朝向z轴的负方向。y轴向上。x轴指向右方。视图变换之后的真实位置取决底层API的实现。
这里描写叙述的空间称为相机空间。通常也称为眼睛空间。图2.4显示了经过视图变换之后的相机与模型,模型变换与视图变换都使用4x4的矩阵实现,这是第4章的主题。
2.3.2 顶点着色
为了生成真实的场景,仅仅渲染物体的外形与位置是不够的。它们的外表也须要被建模,这包括每一个物体的材质。每一个灯光照在物体上产生的效果,材质和灯光能够使用不同的方式进行建模,从简单的颜色到复杂的物理表现。
决定灯光在材质上表现效果的操作称为着色(shading)。包括在物体的不同顶点上计算着色方程,典型地,某些计算在几何阶段作用在模型的顶点上,其他的可能发生在逐像素光栅化期间。每一个顶点都能够存储一些材质数据,如点的位置,法线,颜色以及其他计算着色方程须要的不论什么数值信息。顶点着色的结果(可能是颜色,向量。纹理坐标以及其他类型的着色数据)被发送到光栅化阶段进行插值。
通常着色计算一般发生在世界空间中,实践中,有时也非常方便将相关的实体(镜头,灯光)变换到其他空间来进行计算,这是实用,当參与着色计算的全部实体都被转换到同一空间灯光。相机以及模型之间的相对关系得以保留。
贯穿本书着色会被深入地讨论,特别是在第三与第五章。
2.3.3 投影
着色之后渲染系统运行投影,将观察体置换到点(-1,-1,-1)到(1,1,1)的单位立方体内,单位立方体也称为规则观察体。有两种经常使用的投影方法,各自是正交投影(也称平行投影)和透视投影。如图2.5。
观察体的正交视图一般是一个矩形盒子,正交变换将观察体转换到一个观察立方体,正交投影的主要特点是变换之后平行线依旧是平等的。正交变换是平移与放缩的组合。
透视投影有一点复杂,在这样的类型的投影中。投影之后远离相机的物体看起来更小一点,另外。平行线在无限无处汇聚在一起。透视变换模仿我们观察物体的尺寸。观察体也称为锥体。是一个被矩形截断的角锥体(金字塔),该锥体也被转换到单体立方体。正交和透视变换都能够被构造成一个4X4的矩阵(见第四章),经过变换之后,模型也被称为放在了规一化设备坐标系中。
从一个体到还有一个矩阵变换被称为投影,由于变换之后。z坐标是不会存储在生成的图像中的,经过投影模型从三维变成二维。
2.3.4 裁剪
仅仅有图元全部或部分在观察体才会被传递到光栅化阶段。然后绘制在屏幕上。全部在观察体内的图元以原样传递到下一个阶段。完毕不在观察体内的图元既然不会被渲染也就不会再被往下传递了,部分在观察体内的图元须要裁剪。比如,一条线的一个顶点在观察体内还有一个顶点观察体外须要依据观察体进行裁剪,所以观察体外的那个顶点须要被该线与观察体之间相交的点所取代。
投影矩阵的使用意味着使用单位立方体裁剪。
裁剪之前使用视图变换的优势在于使得裁剪问题变得一致,图元的裁剪总是依靠单位立方体,图2.6描写叙述了裁剪的流程。除了观察体的六个裁剪平面之外,用户也能够定义其他的裁剪平面来剔除物体。一张图片显示了这样的类型的可视化,也称为分片(sectioning),如图14.1。
与之前典型地运行在GPU上几何阶段不同。裁剪阶段(以及后面的屏幕映射阶段)在特定的硬件上运行。
2.3.5 屏幕映射
仅仅有观察体中(被裁剪过)的图元才被传递到屏幕映射阶段。当图元进入该阶段时也依旧是三维的,每一个图元的x和y坐标被置换成屏幕坐标,屏幕坐标与z坐标组成了窗体坐标。如果场景被渲染到的窗体的最小角在
和最大角是
,当中
和
,然后变换之后接下来是缩放操作。
z坐标不受映射的影响,x和y坐标被称为屏幕坐标,xy与z
坐标被传递到光栅化阶段,屏幕映射的过程如图2.7所看到的。 一个令人迷惑的是整型和浮点数是怎样关联到像素(纹理)坐标。DirectX 9及其前代使用0.0作为像素中心的坐标系统。意味着[0,9]的像素范围覆盖的范围是[-0.5, 0.95)。
Heckbert[520]描写叙述了一个更一致的策略,给定一个使用笛卡尔坐标系水平像素数组。像素最左边缘是浮点数0.0,OpenGL,DirectX10及后代使用这样的策略,该像素的中心点是0.5,所以[0,9]的像素覆盖的范围是[0.0, 10.0),这个转换可简单地表述为:
当中d是像素的离散(整型)索引。c是像素内的连续浮点数。
对全部API来说像素位置增长都是从左到右。 而位置0是在顶部还是底部OpenGL和DirectX是不一样的。OpenGL使用笛卡尔坐标系以左下角作为最小值。而DirectX有时依据上下文的不同以左上角作为最小值。他们都是有道理的,之间的区别并无对错。举个样例,(0,0)在OpenGL中位于图片的左下角,在DirectX中位于图片的左上角,DirectX的原因是由于屏幕上的一些现象是从顶究竟的,微软窗体使用这样坐标系统。我们阅读也是这个方向。而且非常多图片格式也是以这样的方式存储缓存区。关键的问题是两者区别的存在,而且当转换API时须要考虑到这一点。