细心的玩家可能会奇怪,为什么在近一年的时间内,会冒出如此多的抗锯齿技术?要回答这个问题就不能不谈到延迟渲染。相信《微型计算机》的读者,对延迟渲染(关于延迟渲染的详细介绍,可阅读本刊在2011年4月下刊登的《SRAA新型抗锯齿技术初探》)这个已被热炒许久的概念并不陌生。它带来的高效率光照计算使得游戏场景中能够出现更多更复杂的动态光源,因此近年来得到迅速发展,被包括《战地3》、《地铁2033》等在内的诸多游戏大作采用。
但延迟渲染的到来却使得通常使用的MSAA(多重采样抗锯齿)光华顿黯——MSAA与延迟渲染并不兼容。MSAA是面向前向渲染的抗锯齿技术,在使用延迟渲染设计的游戏中,MSAA将“退化”成暴力的超级采样抗锯齿,其相对高效率的优点荡然无存。延迟渲染广泛应用的现状也使得学术界开始重新审视传统MSAA技术的天生劣势。根据GDC 2011大会上透露的数据,使用GeForce GTX 470在目前的游戏场景上进行MSAA 8x处理平均需要5.4毫秒,显存占用达到126MB之多,开启延迟渲染之后更是飙升到506MB,开启HDR之后还需再加倍,天文数字般的代价使得MSAA的采样倍数被限制在了4x以下,而这又导致了图像质量的降低。
在学术界和工业界的不断探索下, 英特尔实验室提出的MLAA(形态抗锯齿)技术脱颖而出。这项技术揭开了后期处理式抗锯齿技术蓬勃发展的序幕,由于MLAA处理所需的数据仅仅是像素的颜色值,因此获得了卓越的兼容性,同时其理想状况下的处理质量甚至可以超越MSAA。
根据目前对人脑视觉识别的研究结论,锯齿图案比颜色失真更加容易被人眼捕捉到。因此为了消除锯齿可以付出颜色准确度上的代价。基于此,MLAA将检测每帧图像中的颜色不连续信息,进行模式识别,把这些颜色上可感知的边缘组合成Z、U、L形状,并将这些边缘上的像素颜色根据覆盖区域的大小计算权重,与周围的颜色进行混合,从而达到平滑锯齿的目的。但是原始的MLAA算法是为CPU设计的,不经过优化改造是无法使用在实时渲染上的。
图1:MLAA的基本处理规则——根据Z、U、L形状获知原始的边缘信息(近似长方形的方框),然后计算方框覆盖的轮廓区域大小,将边缘颜色进行混合。
根据SIGGRAPH 2011上的讲座介绍,使用原始的MLAA代码在XBOX 360上花费了几乎90毫秒/帧的处理时间,光是权重计算的步骤就付出了65毫秒,长得难以接受。于是一系列针对MLAA的优化改造工作如火如荼地展开,CPU+GPU的混合式MLAA、整体移植到GPU上的FXAA以及Jimenez MLAA相继出现,终于将处理时间缩减到了几毫秒甚至零点几毫秒的量级上。受到MLAA的鼓舞,SRAA等同样基于后期处理思想的抗锯齿技术也在此期间诞生,它们兼备良好的质量与低廉的实现成本,因此受到了N、A两个阵营的关注。与《战地3》一同声名鹊起的寒霜2引擎就同时内置了FXAA和SRAA两种技术。至此,延迟渲染为抗锯齿技术筑起的性能瓶颈已经被突破,高质量的抗锯齿技术已经能够在主流显卡上与延迟渲染协同工作。
虽然MSAA留下的空白已被填补,但后期处理抗锯齿技术仍然存在缺陷,主要有:
物体原有的形状未能得到较好保留,存在过度模糊的现象。例如Johan Andersson就将由MLAA演化而来的FXAA戏称为“模糊抗锯齿”。过度的模糊甚至影响到了一些纹理细节的表现。
忽略了对角线模式的检测,导致抗锯齿质量的降低。现有的抗锯齿技术普遍存在这一弱点, 从MLAA到新近的SRAA无一例外,只是受影响的程度不同。SRAA的处理质量稍好,MLAA则相对糟糕。需要一个新算法将二者的优点进行融合。
高光和着色上的锯齿没有较好地移除,子像素级别上的特征没有较好保留。这是一个普遍缺陷。
局部对比度没有纳入考量,无法准确评估边缘是否被人眼识别,浪费运算资源,这是原始MLAA算法的另一重要缺陷。
对接近水平或者垂直的边缘进行的处理在时间上不稳定,运动图像获益不如静态图像。
为了解决这些问题,SMAA站到了台前。
SMAA全称为增强型子像素形态学反锯齿(Enhanced Subpixel Morphological Antialiasing)。它的基本处理流程建立在Jimenez优化改造后的MLAA算法之上,但是每一个步骤都经过了强化或者是彻底的更新:边缘检测技术通过精确距离搜索和局部对比度自适应得到了提升,使得处理结果更加可靠。同时,模式识别方面被尖锐几何特征、对角线检测加以强化,能够在物体轮廓的斜线上产生更加准确的结果。
接下来就让我们将借助SIGGRAPH 2011大会上,Jimenez和Alexander Reshetov等人制作的PPT,来说明SMAA的工作原理。
图2:简单的图像实例,这是进行光栅化之后,MLAA处理之前的图像。
由于SMAA技术来源于MLAA,因此该技术的首要工作仍是利用MLAA技术平滑锯齿。让我们首先从图2开始。每一个方格代表一个像素,可以看到,图像中有着泾渭分明的一条分界线, 为了醒目, 我们用加粗来标示它。这就是颜色上的边缘锯齿,也是MLAA处理所需的全部输入信息。它所要做的,就是根据现有的锯齿状图像,获知原始的边缘信息。这条加粗的边缘线呈现一个“Z”字形的模式。这个“Z”模式由两条垂直边,一条水平边组成。
图3:距离搜素和重新向量化。
如图3所示,从点状标记出发,分别向水平边的左右方向延伸,直到碰见左右两侧的第一个垂直转角,我们就找到了“Z”模式中蕴含的两条垂直边,也就是图中用椭圆圈住的部分。本质上来说,我们是在一条水平线上行走,直至碰见左侧的“峭壁”,和右侧的“悬崖”。这些垂直于搜索方向上的悬崖峭壁就是所谓的“交叉边”,它代表着距离搜索的终点。距离搜索结束后,可以得到d(left)和d(right)所代表的水平边缘长度。有了交叉边和长度信息,就可以画出具有一定斜度的边缘线条,我们暂且将之称之为逼近线。这对MLAA反锯齿计算是至关重要的一步。寻找d(left)和d(right)的步骤就是距离搜索,这个步骤会告诉我们需要处理的边缘大致有多长,画出具有一定斜度的逼近线条的步骤被称为重新向量化,它会重建出近似的边缘信息,以便进行接下来的模糊处理。那么重新向量化、模糊处理这两步工作对于平滑锯齿会有怎样的帮助呢?
图4:边缘线条将某些像素一分为二,这种现象发生在光栅化的过程当中。
为了理解这一点,让我们接下来观看图4。假设有一个黑色物体,它的一条边(为了醒目,这条线被人为地加粗),从正待我们处理的画面中横贯而过,我们将它称之为原始边缘。那么根据光栅化的处理原则,在加粗线条之下的区域,也就是黑色物体内部,应该被着上黑色,而加粗线条之上的区域没有任何物体显示,应该被留白。我们注意到,这条加粗线很不“乖巧”地把图中部分像素一截为二,但一个像素只能同时显示一种颜色,没有办法“脚踩两只船”,那它们应该是被着黑还是留白呢? 答案是,如果没有做多倍采样的话,每个像素的颜色值采样点会位于像素的中心。举例来说, 像素(0,0)完全位于物体内部,它的中心点显然会被着上黑色。不过像素(2,2)就不同了,虽然它有很小的一部分位于黑色物体内,但是它的中心点位于空白区,于是它会被留白。按此处理法则,我们终得到的图像会变为图2。因此在没有见过图4的情况下,想知道图2中的像素(2,2)到底被原始的物体边缘覆盖了多少,是不可能的事情。这就会导致即便像素(2,2)被黑色边缘覆盖了几乎一半,它的着色结果也将是白色; 像素(2,1)上的白色将被彻底“消灭”,完全“涂黑”。这种着色结果的不准确正是画面锯齿诞生的原因之一。
而在使用MLAA技术后,这种情况就不会发生。让我们回过头来看看图3,MLAA技术会跟着这条水平线做边缘搜索,识别出一个“Z”字形模式,并用一条具有斜度的逼近线将两条垂直交叉边连接起来。这些步骤的意义在于,虽然MLAA无力触及光栅化处理前的状况,但是它能够凭借仅有的颜色信息,重建起近似的边缘线,从而得知这些像素大致上被原始边缘线覆盖了多少面积。我们希望这条逼近线能够尽量靠近图4中的原始边缘线,愈加靠近,着色重建的结果也就越准确。这里就是MLAA的精髓思想,在距离搜索与模式的判别中,每发现一个特定的“Z”、“U”、“L”形,都能够画出一段逼近线,例如图1。这个估计并不是百分之百准确,但是实践证明这样做确实有着良好的效果。图3中的逼近线再度将部分像素一截为二,此时MLAA会让它们根据各自被截区域的大小做颜色混合。大部分区域被截在了逼近线条以下的,那么这个像素的颜色就越深,反之亦然。分析着色和留白各自需要混合多少分量的步骤就是权重计算,这是原始MLAA中为耗时的一个步骤。
图5:颜色混合之后的结果,通过颜色的渐变实现了平滑过渡。
从图5可以看到,在经过以上处理后,我们就顺利地实现了颜色渐变的平滑过渡,“消灭”了物体上的锯齿。但MLAA本身也存在问题:由于仅仅使用颜色数据来判断抗锯齿边缘,因此MLAA技术无法辨识到底哪些边缘需要进行抗锯齿计算,从而导致运算资源上的浪费与图像的失真。
而这正是SMAA技术需要做的——改进边缘检测算法。一帧图像中的边缘有很多,但并非每一条都需要处理。据研究,若周围区域里存在一条颜色反差较大的边缘时,人的视觉系统会忽略对比度相对较低的边缘,因此可以把低对比度的部分从处理过程中早早剔除,保留图像的锐度,同时节约了处理时间。
图6:改善对比度适应算法后的处理效果对比。
如图6所示,左起第一张图片中,占据高对比度优势(由浅色Z形线标记)的边缘将对下方的其余边缘(以竖线标记)产生遮盖作用,通常情况下人的注意力将集中在高对比度的边缘上。若是使用MLAA技术,在抗锯齿处理时,不考虑对比度的影响就会带来位居中间的图样,它对不该处理的边缘也做了处理,导致了一串不平滑的颜色改变。而将对比度纳入考量的SMAA技术则会形成右图,此时颜色过渡就更为平滑。
图7:高对比度边缘的计算量对比。
再看图7。以点状标记的是当前的待处理像素,浅色标记的是它的左边缘,可能对这条边缘形成遮蔽作用的其他边缘被进行了加粗,足足有六条之多。若使用MLAA技术,像素的每条边都需要访问这六条边。而使用SMAA技术后,像素总共只需要访问四条边缘,大大降低了访问次数。
同时,在边缘检测中寻找线条延伸终点的步骤也需要频繁的数据访问,这对显存带宽形成了一项挑战。为了提高带宽利用率,在改进版的Jimenez’s MLAA技术中就已利用硬件的双线性插值来加速这个过程。通过一个简单的线性插值编码公式,可以在一次访问中得知两个像素的情况,大大地降低了带宽压力,这一特性被称为精确距离搜索。
图8:双线性插值的搜索模式
如图8所示,颜色加粗的水平线条就是待搜索的边缘。从星形像素出发,到达第一个菱形处,我们就一次性跨越了两个像素,重复这个过程,直到圆圈标示的终点,我们就得到了所要的边缘信息。这里的精髓在于,我们在理论上以两倍速度抵达了目标。而没有引入双线性插值优化的MLAA只能逐像素地访问过去,在这一个步骤上的理论速度只有Jimenez’s MLAA的一半。
图9:Jimenez’MLAA与SMAA的对比
不过虽然图8的方法(如图9左上)能够有效找到水平线条的终点,但是并不完美。它能够告诉我们水平方向上的边缘情况, 但是却会错过垂直线条上的交叉边(图9左下),这是因为Jimenez’s MLAA的双线性插值公式只考虑了一维的情况。SMAA将Jimenez’s MLAA当中的双线性插值公式再度加强,引入了垂直坐标分量(右下),能够在一次访问中获取水平与垂直两个方向上的信息。图9右上图为二者对比,采样点每次只能跳跃到像素垂直边的是Jimenez’s MLAA的跳跃过程,而采样点在像素内中上位置的则为SMAA的跳跃过程。可以看到,SMAA的采样点有所偏移,从像素边缘处移到了像素内部,这样就不必担心错失垂直方向上的信息了。
图10:改进后的精确距离搜索的质量对比。左图为SRAA,中间为SMAA 1x,右图为SMAA 4x,请观察图中白色柱状天线,显然右图结果为平滑。
众所周知,MLAA的一大弱点就是模糊了文字边缘,未能保留文字显示应有的锐利。作为一个在MLAA之上构建的新技术,SMAA要如何解决这个问题呢?答案是:尖锐几何特征检测。
如上文所说,MLAA是依据颜色上的不连续原理来对边缘进行处理,在重新向量化的步骤中, 交叉边在此扮演了重要角色。然而Jimenez等人观察到,MLAA、FXAA技术上采用的交叉边多只有一个像素的长度,但物体上的转角长度往往大于这个值, 因此这些技术无法“知道”哪些是锯齿,哪些是物体自身的转角(见图11)。这就令MLAA、FXAA等技术也会对物体的转角进行重新向量化处理,从而造成物体的转角处出现不应有的模糊效果。SMAA解决这一问题的办法很简单—将交叉边长度扩大至两个像素。
图11:更加精确的重新向量化处理
让我们通过图11来分析这项特性的优势所在。w右侧有着两级阶梯状的锯齿(黑色线圈处),垂直凸起的边长只有一个像素,对此MLAA能够正确地进行重新向量化,一条较长、有斜度的线条横贯八列像素,这就是MLAA恢复出的原始边缘即逼近线。被逼近线条一截为二的那些像素,会根据被截面积的大小计算权重,加以不同的模糊处理,于是锯齿就被平滑了。再看图的左侧,标注了e3的像素上方有一个被正方形线框起的部分,这里有一个90°转角。如果我们根据原始MLAA的处理规则,以一个像素长度的交叉边(加粗的垂直边)来处理,得到的重新向量化结果就是画出另一条斜度很大的逼近线——但是问题出来了。这个90°的转角原本就是物体应有的形状,这里的锐度应该忠实地保留,不需要进行抗锯齿处理。如果我们在这里也画上逼近线,就会将位于90°转角上的这个像素一截为二,由此引入不必要的模糊,不该处理的“锯齿”被处理了,带来了锐度的损失。但如果使用两个像素长度的交叉边,长度扩展至e1处,那么就可以检测到正确的90°转角,画出与水平边重合的逼近线,从而避免出现这个缺陷。
图12:SMAA在文字锐度上轻松击败了MLAA。
从图12中可以看到,SMAA在文字锐度上轻松击败了MLAA。将图像放大可以看到,由于字母“D”内侧出现的交叉边只有一个像素长度,无法改变,被错误地认为是需要处理的边缘,因此也被SMAA施加了模糊化处理,但除非放大图像仔细观察,否则这一改变几乎无法察觉。而交叉边长度明显超过一个像素的字母“E”上锐度则得到了完美保留,没有一丝一毫的抗锯齿处理痕迹。这一关键改进使得SMAA在对付文本时能够尽量保留锐度,从而将MLAA甩在了身后。
图13:MLAA(左)与SMAA(右)对几乎呈45度角的斜线进行重新向量化。由于引入了对角线模式处理,SMAA准确重建了对角线状的边缘。
除了SRAA之外,大部分抗抗锯齿技术检测水平和垂直方向上的边缘,这使得针对斜线的反锯齿结果不尽如人意。SMAA引入了新颖的对角线搜索,搜寻左上—右下,左下—右上两种模式的形状,依旧进行距离搜索,获取交叉边,以此得到相应的覆盖区域。如果发现对角线至少有两个像素长度,那么就进行处理,否则就把它们当成普通边缘。对角线搜索在我们之前提到的水平、垂直边缘搜索之前执行,这保证了对角线将得到优先处理。
图14:左侧为SRAA,右侧为SMAA,显然右图SMAA的处理结果更为平滑、自然。
即便与依靠几何信息( 深度与法线值)做边缘检测,可对对角线进行抗锯齿处理的SRAA相比,SMAA在一些特定场景中的优势也非常明显。如图14所示,路灯上的深度与法线变化很小,SRAA的处理就难以准确表现,而SMAA专门引入了对角线模式的检测,因此只需1x处理,SMAA就轻松将SRAA甩在身后。到了S2x的级别上,SMAA甚至可以与号称黄金标准的SSAA 16x并驾齐驱,对角线检测的引入确实效果卓著。然而SMAA相对于SRAA的优势并不止于此。
图15:子像素特征的渲染,左侧为SRAA,中间为SMAA 1x,右侧为SMAA 4x。
从图15可以看到,SRAA在子像素级别上的重建质量还是可以的,虽然只对颜色值做了1x采样,但是它对其余子像素样本的颜色值估计的确很不错,这在第一排图像中林立的天线与第二排图像中的铁丝网上有所显示,而SMAA 1x的重建质量比较糟糕,不是SRAA的对手,但是SMAA 4x的质量就是毫无疑问的完胜。这个完胜不仅仅在于图像的重建质量,还在于图像的处理时间,就算以4x采样处理,SMAA相对于SRAA也有些许优势。虽然优势不到一毫秒,但是在实时渲染领域,速度实在是至关重要。要知道正是为了抢下几毫秒的时间,索尼旗下的工作室不惜大费周章改进渲染流水线, 拿出了一个SPU+GPU的帧间交替渲染方案, 终才造就了一个低延迟的PS3专属MLAA。SMAA的局部对比度适应处理一般只需0.08毫秒,尖锐几何特征检测和精确距离搜索的时间尚不到0.01毫秒,对角线处理也只需0.12毫秒,速度和质量上的双重优势对开发者而言确实是一个不小的诱惑,目前SMAA已经能够集成进CryEngine 3引擎当中,它是否强大到能够说服更多的游戏开发者使用,唯有等待时间来检验了。
强大的“ 启发式模糊” ,稳定性, 对锐度的保留, 只有MSAA十分之一的处理速度,SMAA的确在MLAA开辟的道路上迈出了更坚实的一步。但是这并不意味着抵达终点。按照学术与工业界的惯例,技术的好坏仍然要等待后续研究与开发应用的进一步反馈和评价,虽然SMAA迅速得到了来自Crytek的支持,但是目前就断言它是后期处理式抗锯齿的终极技术为时尚早。我们仍需谨记一位图形专家的评论:“实时渲染的问题远没有到完满解决的地步。将来会更美好。”