Skip to content

AntiAliasSummary

zilch edited this page May 25, 2021 · 1 revision

抗锯齿算法总结

图像锯齿根据成因大致可分为两类:

  • 几何锯齿
  • 着色锯齿

几何锯齿是由于在光栅化阶段,受成像分辨率所限,导致几何体的边缘呈锯齿状。

而着色锯齿则是在ps阶段,由于渲染引起的物体表面色彩高频变化。

这里罗列以下常见的游戏当中的抗锯齿技术:

  • SSAA
  • MSAA
  • SMAA
  • FXAA
  • TAA

1. SSAA(Super Sample Anti Aliasing)

以高分辨率渲染,然后再降分辨率输出。

例如目标屏幕分辨率为600x800,那么先以1200x1600分辨率渲染,然后DownSample到600x800,如此一来,屏幕上的单个像素最终由2x2个像素混合而成,因此起到抗锯齿效果。

优势:

  • 效果好

劣势:

  • 性能开销巨大。
  • 显存、带宽占用均消耗很大

2. MSAA

具体可以参考[1]这篇文章,介绍的比较详细。这里简单总结如下:

  • 在一个像素内部生成若干采样点
  • 针对采样点进行覆盖测试和深度测试
  • 一个像素至多运行一次片段着色(假如有内部采样点通过测试)
  • 将颜色复制给通过测试的采样点
  • 对所有采样点进行混合(Resolve),得到像素最终颜色。

优势:

  • 硬件支持
  • 片段着色保持X1不变(一个像素只执行一次PS)

劣势:

  • 显存占用同SSAA
  • 只能处理几何走样,无法处理Shading走样、AlphaTest走样等等
  • 难以兼容延迟渲染
  • 对于一些复杂的几何场景,开销可能会高于基于后处理的一些AA算法

3. SMAA

SMAA是MLAA的GPU优化版本(MLAA是纯CPU抗锯齿),因此两者的思路是一致的。 SMAA属于图像后处理抗锯齿算法。其原理可以概述如下:

  • 通过算法判定当前像素是否为边缘
    • 这里可以是基于亮度的、或者depth的、或者normal+objectInstanceId的。
    • 这作为单独的一个Pass,将生成一张EdgeTexture
  • 针对边缘像素,往边缘两侧(MainDirection)搜索直到尽头,得到两个端点。在端点处,往交叉方向(Cross Direction)采样,以确定锯齿形态,总共24种锯齿形态。根据锯齿形态,来计算权重贴图。这是第二个Pass。
    • 为了加速计算过程,会使用一张预生成的AreaTex。
  • 根据权重贴图,与周边像素进行混合。这是第三个Pass。

英文原版可以参考此篇: [6] Jorge Jimenez, Subpixel-Morphological-Anti-Aliasing, 2011

或者中文Blog可以参考此篇: https://www.qiujiawei.com/antialiasing/

4. FXAA(Fast Approximate Anti-Aliasing)

FXAA是SMAA的简化版本。主要的理论方向是一致的,但是不会那么细致的去区分各种锯齿形态。其在边缘判定和形态判定算法上做了一定的简化,仅需一个Pass即可。牺牲一定的效果以获得性能的提升。详细的FXAA理论技术分析请参考此篇: FXAA算法演义

优势:

  • 显存占用低
  • 无硬件要求
  • 可以处理Shading引起的走样
  • 性能开销固定

劣势:

  • 由于FXAA对所有颜色边缘进行柔化,会导致无差别的模糊

使用FXAA有如下的注意点:

  1. 在HDR模式下,FXAA必须在ToneMap到LDR空间后再进行
  2. 如果渲染计算是在线性颜色空间进行,那么FXAA必须在转到sRGB空间后再进行

关于第1点,[3]中描述如下:

For example a 0.0 intensity pixel and a 16.0 intensity pixel will average to a 8.0 intensity pixel which later might get tone-mapped to 1.0 intensity. (which results in no blend between the two pixels).

这个不难理解,因为HDR到LDR的映射不是线性的。因此即便在HDR空间进行反走样计算,在ToneMap后依然会失去"平均"的效果。

关于第2点,[3]中描述如下:

FXAA requires the non-linear (perceptually encoded) RGB input and texture filtering: as a performance optimization, the algorithm’s end-of-edge search step samples halfway between a pair of texels, and it is important that the fetch returns the perceptual blend of the two texels instead of the linearly correct blend.

5. TAA (Temporal Anti-Aliasing)

TAA时利用历史帧,来进行超采样的抗锯齿技术。其步骤如下:

  • 对投影矩阵进行抖动,以达到每帧采样uv在像素内部进行抖动。
  • 理论上来说,我们将N帧采样结果进行混合后,就能得到超采样抗锯齿的效果。
    • 但实际上,不可能存下N帧历史图像。因此仅存上一帧历史图像,并进行加权混合。

由于摄像机会运动,因此前后两帧摄像机的位置可能并不相同。因此在采样上一帧的像素时,需要:

  • 保存上一帧的投影矩阵
  • 根据当前帧像素的世界坐标,利用上一帧的投影矩阵,即可还原出上一帧的UV,并进行采样。(如果uv超出,则废弃)。

由于场景中存在运动的物体,因此即便摄像机静止不动,同一个位置的像素也会因为物体的运动而发生变化。因此需要:

  • 保存一份VelocityBuffer,记录了每个像素的速度。
  • 根据当前帧像素的世界坐标,利用速度向量反推出其在上一帧的世界坐标。

知乎有详细介绍的一篇文章 - chopper - 深入浅出Temporal Antialising

参考

[1] 深入剖析MSAA

[2] RenderBufferLoadAction&RenderBufferStoreAction的详细说明

[3] Timothy Lottes, FXAA White Paper, 2009

[4] Simon Rodriguez, Implementing FXAA, 2016

[5] SIGGRAPH 2011 presentation on FXAA 3.11

[6] Jorge Jimenez, Subpixel-Morphological-Anti-Aliasing, 2011

[7] https://www.qiujiawei.com/antialiasing/

[8] 深入浅出Temporal Antialising

Clone this wiki locally