目前為止,MSAA仍是抗鋸齒效果的黃金標准。然而MSAA需要硬件支持,並且要在RT中存放子像素信息,這大大增加了內存和帶寬開銷。在使用HDR管線或者G Buffer時此問題顯得更加嚴重。
由於這些限制,基於后處理的抗鋸齒方案逐漸成為主流。這類方案並不需要改變渲染管線,而是在圖片中尋找被人眼識別為鋸齒的像素,再對應模糊處理。morphological antialiasing(MLAA)即是其中之一。
MLAA的思路很簡單,考慮鋸齒圖中的一個微元,它常常是下圖中B的樣子。而如果分辨率無限加大,可以用一條藍線來標定實際的幾何邊界,如圖A。如果我們能知道藍線的實際形狀,就可以根據直線斜率計算藍線下面積與整個像素塊面積之比a,然后用如下公式輕松實現抗鋸齒效果(如圖C):
Cnew = a*Cold + (1-a)Copp (其中Cold是處理前的顏色,Copp 是鋸齒邊(edgel)另一側的對應像素。)
藍線的斜率等於豎直跨度/水平跨度,對於水平鋸齒邊,豎直跨度永遠為2個像素,要解決的問題只有3個:
1)待處理像素在鋸齒邊上的位置
2)鋸齒邊的水平跨度(或豎直跨度)
3)鋸齒邊界的形狀,如下圖。
這三個問題可以一起解決:
從待處理像素開始,沿鋸齒邊分別朝兩側搜索,尋找截邊(crossing edge)
鋸齒邊的跨度以及像素所處的位置可以由左右搜索距離dleft和dright確定。
鋸齒邊界的形狀則由兩側截邊的情況而定。
左圖黃圈內即是截邊需要考慮的像素。中圖列舉了所有可能的9種情況,其中情況6並不需要做抗鋸齒處理。
右圖為AreaTex范例,每一塊記錄了一種情況下對應像素抗鋸齒所需的混合權重。
然而,搜索過程和鋸齒邊界的判斷需要大量采樣,拿到采樣結果后進行重新矢量化時還有大量的分支判斷問題(如上圖右側的9種情況)。Jimenez通過巧妙利用硬件免費的bilinear filter來大量減少采樣數;再引入一張預計算的AreaTex,使用像素位置、鋸齒邊跨度和邊界情況作為索引,直接取出最終抗鋸齒所需的混合權重。
至此MLAA的問題都得到解決,性能也足以流暢的運行。
讓我們再重新梳理一下MLAA的算法框架。它基本分為如下三步進行:
1. 尋找位於鋸齒邊緣的像素,並標記出來。
2. 重新矢量化。
3. 混合對應像素。
一、邊緣檢測
邊緣檢測可以基於Depth,亮度,顏色或者其中幾種混合判斷。
算法需要檢測水平和豎直兩條邊。 每個像素有4個相鄰像素,理論上應該做4次邊緣檢測。但由於像素之間公用邊,所以只要針對左側和上側的相鄰像素進行檢測。
這部的處理結果是用像素標記出的鋸齒邊。
二、重新矢量化
這一步的處理單元並不是像素,而是鋸齒邊。設定一個最長搜索距離,從當前位置起分別針對水平和豎直方向的鋸齒邊進行重新矢量化。重新矢量化的過程大量利用雙線性采樣,並最后采樣AreaTex得出混合權重。
三、混合對應像素
這步根據混合權重來執行最終的抗鋸齒過程,同樣也可以使用手動設定采樣位置配合免費的雙線性采樣來優化效率。
由於這一步的處理單元是像素,而不是鋸齒邊,所以並不方便將它與第二步合並。
圖2中,紅色表示像素左側存在鋸齒邊,綠色表示像素上側存在鋸齒邊,黃色表示二者都有。
圖3中,RG表示水平鋸齒邊上下兩側像素的混合權重;BA通道存儲了豎直鋸齒邊左右兩側像素的混合權重。
參考資料:
GPU Pro 2 Practical Morphological Antialiasing
Siggraph2011 Filtering Approaches for Real-Time Anti-Aliasing