FXAA、FSAA与MSAA有什么区别?效果和性能上哪个好?
链接:https://www.zhihu.com/question/20236638/answer/44821615
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
首先所有MSAA, SSAA, FXAA, TXAA等都是抗锯齿(Anti-Aliasing)技术。
锯齿的来源是因为场景的定义在三维空间中是连续的,而最终显示的像素则是一个离散的二维数组。所以判断一个点到底没有被某个像素覆盖的时候单纯是一个“有”或者“没有"问题,丢失了连续性的信息,导致锯齿。
最直接的抗锯齿方法就是SSAA(Super Sampling AA)。拿4xSSAA举例子,假设最终屏幕输出的分辨率是800x600, 4xSSAA就会先渲染到一个分辨率1600x1200的buffer上,然后再直接把这个放大4倍的buffer下采样致800x600。这种做法在数学上是最完美的抗锯齿。但是劣势也很明显,光栅化和着色的计算负荷都比原来多了4倍,render target的大小也涨了4倍。
MSAA(Multi-Sampling AA)则很聪明的只是在光栅化阶段,判断一个三角形是否被像素覆盖的时候会计算多个覆盖样本(Coverage sample),但是在pixel shader着色阶段计算像素颜色的时候每个像素还是只计算一次。例如下图是4xMSAA,三角形只覆盖了4个coverage sample中的2个。所以这个三角形需要生成一个fragment在pixel shader里着色,只不过生成的fragment还是在像素中央(位置,法线等信息插值到像素中央)然后只运行一次pixel shader,最后得到的结果在resolve阶段会乘以0.5,因为这个三角形只cover了一半的sample。现代所有GPU都在硬件上实现了这个算法,而且在shading的运算量远大于光栅化的今天,这个方法远比SSAA快很多。顺便提一下之前NV的CSAA,它就是更进一步的把coverage sample和depth,stencil test分开了。
MSAA的一个问题就是和现在大街小巷都是的deferred shading框架并不是那么兼容。因为用deferred shading的时候场景都先被光栅化到GBuffer上去了,不直接做shading。硬要做的话可以看我之前写的这个SDK Sample(Antialiased Deferred Shading,大概思路就是用各种方法检测一下哪个pixel是被多个fragment cover的才手动做super sampling)。
因为MSAA这个问题现代引擎里都用的是Post Processing AA这一类技术。这一类东西包括FXAA,TXAA等,不依赖于任何硬件,完全用图像处理的方法来搞。有可能会依赖于一些其他的信息例如motion vector buffer或者前一贞的变换矩阵来找到上一贞像素对应的位置,然后再做一些hack去blur或者blend上一贞的颜色等。通常非常hacky,FXAA的发明人原来是我们组的,他自己都不知道这个为什么会work- -”,但是精心调校之后后效果还是很好的,例如下面是UE4的Post Processing AA开关对比图:
最后再扯一下NV最新的那个MFAA(Multi-Frame AA),因为Maxwell架构支持的programmable coverage sample location,所以可以做到贞间用不同的coverage sample位置,当FPS足够高的时候,2xMFAA就可以达到4xMSAA的效果。
对玩家来说,看着舒服就行。当然像使命召唤这种明明是forward rendering还要用SSAA来抗锯齿的,在显卡烂的机子上开还是要慎重的。