当三角形的顶点转换到裁剪空间后,我们对三角形做两个重要测试。注意,这里讨论的顺序并不一定是硬件执行的顺序。
背面剔除
第一个测试称作背面剔除,其目的是去除背面摄像机的三角形。在标准三角网格中,我们永远看不到三角形背面,除非进入那些多面体内部。去除这些三角形并非必要,画出它们依然得到正确的图像,因为它们会被前方的三角形盖住。但我们不想浪费时间去绘制任何看不见的物体,所以我们常做背面剔除,特别是在理论上有一半的三角形为背向的。
实践中,只有少于一半的三角形能被剔除,特别是静态场景中,创建时就没有背面(如地形面)。当然,也还能去掉一些背向三角形(比如山背后),但如果我们高于地面,多数面仍为正向的。然而,动态物体就有可能节约一半的背面了。
有两种方法可用于探测背向三角形。第一种是裁剪和投影的,在裁剪空间(或摄像机空间)中进行的。基本思想是判断眼睛是否在三角形所在平面的前面,如图
15.23所示,将背向剔除的面都用灰色绘制。注意背向剔除不依赖于视锥,实际上,它甚至不依赖于摄像机朝向,只考虑三角形与摄像机的相对位置。
为在3D中执行背面剔除,需要三角形法向量和一个从眼睛到三角形的向量(可取三角形上任何一点,我们经常任取一顶点)。如果上面两个向量的方向大致相同(点积大于0),则三角形为背向的。前述背面剔除方法主要用于软件渲染的时代,那时候预先计算好的表面法向量存储在三角形级。如今,由于向渲染硬件投送几何体已经称为瓶颈,这类多余的信息都不再发送了。当今图形硬件上,通常利用屏幕空间中三角形顶点的顺序(顺时针或逆时针)进行背面剔除。这里约定,从前面看时,三角形顶点顺序为顺时针。于是,便可剔除那些逆时针顶点顺序的三角形。API允许用户控制背面剔除,有时可以在渲染特殊几何体时不进行剔除,或者当物体反转的时候可将前面的剔除顺序反过来。
裁剪
即使正对摄像机,三角形也可能部分或完全在视锥外而不可见。在投影到屏幕空间之前,一定要确保它们完全在视锥内,这个过程称作裁剪,裁剪一般由硬件完成。标准多边形裁剪算法是Sutherland-Hodgman算法,它将多边形分裂为多个小多边形来解决裁剪问题,裁剪完后再组合起来。对平面做多边形裁剪时,沿边遍历多边形,依次对每边进行裁剪。边的两个顶点要么在或不在平面内,所以总共有四种情况,每种情况产生0、1、2个输入点,如图15.25:
图15.26显示了右裁剪多边形的情形。注意,裁剪输出顶点而不是边。图15.26中,边画出来只是为了说明。特别是最后一步似乎产生两条边,但实际只产生一个顶点----最后一条边只是为了封闭多边形加上的。
在每一阶段的最后,如果保留的顶点数少于三个,则多边形不可见(注意1个或2个顶点无法组成多边形,输出顶点数只能为0或至少3个)。一些图形硬件不在3D中做所有6个面的裁剪,而代之以近面和2D裁剪。
光栅化
裁剪以后,根据公式15.6,顶点终于可以投影到屏幕坐标了。当然这些坐标是浮点型的连续坐标,而我们渲染的像素是离散的,所以如何判断对应关系?开发一个算法是非常困难的。如果算法错误,三角形之间会出现裂缝。如果我们做混合,重叠的三角形也会显示出来。从另一方面说,必须保证渲染三角形代表的平面时,每像素只渲染一次。幸运的是,图形硬件保证了这一切。
虽然,我们不必知道硬件如何决定某像素属于某三角形,但还是有必要了解对一个单独的像素,它会做些什么。概念上有三步:
(1)着色:像素着色指为像素计算颜色的过程。一般,像素先光照再雾化,像素着色的输出值不但有RGB,还有alpha值表示透明,用于混合。
(2)测试:拒绝像素一般有三种测试方法。裁剪测试去除渲染窗口外的像素(假如做了完整的视锥测试则不必要),深度测试用z缓冲去除像素,alpha测试以alpha值为基础去除像素。可以使用多种alpha测试,但最常见的是去除过分透明的像素(我们不希望这类像素写入深入缓存)。
(3)写入:如果像素通过了深度测试和alpha测试,则更新帧缓存和深度缓存。深度缓存用新值替代旧值即可,帧缓存复杂一些,如果不需要混合,则用新的像素颜色替代旧的值;否则就进行新旧颜色的混合,依据alpha值决定它们各自的贡献。根据不同的图形硬件,也可执行一些其他运算,如加、减。乘。