顯卡帝揭秘AA抗鋸齒的前世今生
AA(Anti-Aliasing)抗鋸齒想必不少玩家在遊戲畫質設定中經常會遇到,說通俗一點AA抗鋸齒的作用:將圖像邊緣及其兩側的像素顏色進行混合,然後用新生成的具有混合特性的點來替換原來位置上的點以達到柔化物體外形、消除鋸齒的效果。隨著圖形技術的不斷革新,AA抗鋸齒的技術也隨之在不斷的發展和改進。面對遊戲畫質設定選項中「品種繁多」的AA抗鋸齒,我們玩家應該如何選擇了,你是否對沒一種AA抗鋸齒選項有所了解?那麼今天顯卡帝就來為您詳細解讀AA抗鋸齒的前世今生,讓你開開心心對AA抗鋸齒弄個明白。
顯卡帝揭秘AA抗鋸齒的前世今生
從本文中,網友朋友將會和顯卡帝共同來探討和解密如下問題:
一、AA抗鋸齒技術的基本原理是什麼;
二、Hardware AA的特點及相關AA技術;
三、Post process AA的特點及相關AA技術;
四、Hybrid AA的特點及相關AA技術;
以上目錄也正是本文的大致行文思路,顯卡帝希望能夠通過循序漸進的分析與解讀讓眾多玩家能夠對AA抗鋸齒有更深入的認識,並且能夠在讀完本文之後能對AA抗鋸齒技術的大致分類有個清楚的認識。
詳解AA抗鋸齒基本原理
AA(Anti-aliasing):標準翻譯為「抗圖像摺疊失真」。說通俗點,AA就是在柵格化圖形中次像素精確級的渲染技巧。因為電腦屏幕顯示單位是像素,它是屏幕上最小的那一個個小方塊。大家只要靠近電視仔細觀察就會發現一個個紅綠藍色的小點,這即是像素點。然而,曲線和角的如果用方塊狀的像素來表現,這顯然是「不大方便的」,因為曲線和角容易產生「狗牙般」的鋸齒。AA就是解決這一難題的一項技術,其目的就是讓圖像看起來更加平滑自然。總之,進過AA處理過後的圖像消除了鋸齒所帶來的「方塊感」。
左邊的圖是非常平滑的,但右邊的則顯得一塊一塊的
從上面這張圖我們可以很直觀的看出未採用AA抗鋸齒技術處理的圖像要比採用AA抗鋸齒處理過後在「方塊感」上面要嚴重許多。
AA的前提非常簡單。請看下面這個圖表:
圓的平滑過渡
首先假設你要想在屏幕上表現一個圓,若圓的尺寸很大,那麼通過很多很多的像素進行排列即可,但如果要表現一個小尺寸的圓,因為提供給你所控制的像素點數量很少,故而通過像素方塊所構建起來的圓最後可能是啥也不像。此刻,AA抗鋸齒正好幫上了大忙。我們先將圓放大(最左邊第一個圓),再將其和一個像素柵格對齊,每個方塊代表一個像素。這時你會發現柵格裡的好多像素都沒有填滿,且填充的比例也不盡相同。然後,我們的目標就是找出這些不完全填充的格子,根據填充的比例挑選基本色(這裡是黑色)的相應比例來填充進去,即得到了第四個圓。仔細分析下這個圓,全填黑色的是那些格子裡完全填充的,而某些50%填充的就填入一個50%的灰進去,75%的就填入75%的灰,等等。最後我們將填好圖的第四個圓縮小為原始大小,即得到了第5個圓,效果是不是很不錯哈。不過這種方法只部分適用於「像素藝術」領域裡,因為像素點的尺寸和顏色的數量都是有限制的。
值得一提的是,AA有正確的用法也有錯誤的用法。正確的方法是如上面所示造成平滑過渡的感覺。錯誤的方法是像下圖的最左邊的圖在黑色邊線的外圍全部加上50%的灰度像素:
AA有正確的用法也有錯誤的用法
剛剛接觸AA抗鋸齒時,人們往往會犯一個錯誤:即將每一「步」都加入一單個淺色像素。其實這種方法顯的十分糟糕。中間的方法是正確的:只再需要的地方加適合的過渡像素。雖說此刻弧線開起來平滑了些,但鋸齒感還沒有完全消除。最後邊的則是最佳的方法:加兩層過渡色,弧線看起來變的更加平滑。所以,單個的分離像素通常不是最好的AA過渡,而同色線條或像素組可以將AA效果表達得更好。
OK,以上介紹了AA的基本前提,不過你會發現我們僅僅介紹了黑白兩種顏色的情形。倘若換成彩色,又該怎麼辦了?其實方法和黑白情況下的AA過渡差不多,只是不再是檢查黑色的百分比例,而是檢查每種顏色的比例了。上圖:
每一個方塊代表著兩種或三種不同顏色之間準備用像素來過渡
左邊第一個,是黑色和白色(在上面我們已經討論過了)。我們找到用來過渡黑與白的過渡色是一種中間灰。這個顏色是靠混合白色所佔的比例之白色和黑色所佔的比例之黑色混合而得到的。同樣混合紅色和黃色,我們得到橙色,然後深綠+藍色=海藍色,在最右邊我們有一點點變化:3種顏色在一起。我們用同樣的方法來對待,混合之後得到一個有點藍的紫色。方法確實並不複雜,但這些都是在可以無顏色限制情況下使用的,因為實際情況中是不可能有一個無限色盤來做AA過渡的,即使有也很費時間。所以我們只能用不斷嘗試的方法來選出合適的AA過渡色,直到成功為止。
AA前世今生之:Hardware AA
進過了前面對AA抗鋸齒技術原來剖析,相比玩家對AA已經有了一個初步的認識。AA抗鋸齒技術在進過幾十年的發展,從離線渲染逐步過渡普及到實時渲染的時代,AA在圖形學中被廣泛地用於了提升渲染質量上面。接下來,我們就對實時渲染中所使用的AA方法的前世今生做一個詳細闡述。首先我們要講的是由硬體支持的AA方法。
圖1:一個像素內部的採樣點
上圖是一個像素內部的採樣點。16個紅圈表示16個採樣點,藍色和黃色是覆蓋了這個像素的兩個三角形。我們通常所說的幾倍抗鋸齒指的就是一個像素點內的採樣點數。
SSAA(Super Sampling Anti-Aliasing)超級採樣抗鋸齒
SSAA是最為直觀的一種AA,也是很早期的一種AA抗鋸齒方法。其基本思想是:這樣就等於把一幅模糊的大圖,通過細膩化後再縮小成清晰的小圖。其實現方法之一:先渲染一個大圖,再Downsample(降低採樣率),這可以等效為在每個最終像素內部做了一個均勻分布採樣。更通用的描述是,每個像素分布多個採樣點(可以均勻分布、Poisson分布、隨機分布、抖動分布等),每個採樣點都有獨立的color和depth,pixel shader在每個採樣點都執行一遍。如上圖的情況,會得到1個白色,1個淺藍色和14個黃色的採樣點。最後這個像素的值是這16個採樣點的平均,也就是白色((1, 1, 1) + 淺藍色 (0.77, 0.77, 1) + 14 * 黃色(1, 1, 0)) / 16 = (0.98, 0.98, 0.125)。在這些方法中,SSAA質量最好,畢竟是個最原始最暴力的方法。在D3D 10.1+上可以選擇per-sample或者per-pixel執行pixel shader,也就是直接支持了SSAA。性能統計(採樣數為N,下同):每個像素裡PS(pixel shader)執行次數為N,佔用空間N個color + N個depth。總之SSAA抗鋸齒,簡單直接但比較消耗資源。
MSAA(MultiSampling Anti-Aliasing)多重採樣抗鋸齒
MSAA是一種特殊的超級採樣抗鋸齒(SSAA)。MSAA首先來自於OpenGL,具體是MSAA只對Z緩存(Z-Buffer)和模板緩存(Stencil Buffer)中的數據進行超級採樣抗鋸齒的處理。其基本思想是:只對多邊形的邊緣進行抗鋸齒處理。我們知道SSAA需要在每個採樣點都執行一次PS並保存color和depth,時間和空間開銷都是相當驚人的。MSAA的出現極大地改善了這一點。MSAA在每個像素只執行一次PS,輸出顏色寫入所有通過depth-stencil測試的採樣本中。在Shader Model 3之前,PS的輸入一定取自像素的中心;後來加入了centric插值,PS的輸入屬性就可以是三角形所覆蓋的所有採樣點的中心:
有無centric插值的對比
如圖1的情況,沒有centric插值的話,藍色三角形的兩個採樣點將都得到純藍的顏色(外差而得),最終像素的顏色就是(2 * (0, 0, 1) + 14 * (1, 1, 0)) / 16 = (0.875, 0.875, 0.125)。有centric插值的話就是個更正確的淺藍色((1, 1, 1) + (0.77, 0.77, 1)) / 2 = (0.885, 0.885, 1),最終像素顏色是(2 * (0.885, 0.885, 1) + 14 * (1, 1, 0)) / 16= (0.98, 0.98, 0.125)。如下圖所示:性能統計:每個像素裡PS執行次數為每個覆蓋到該像素的三角形一次,佔用空間N個color + N個depth。總之,MSAA對資源的消耗需求大大降低,不過在畫質上略不如SSAA。
CSAA(CoverageSamplingAnti-Aliasing)覆蓋採樣抗鋸齒
NOAA,MSAA,CSAA的對比
CSAA是NVIDIA在G80及其衍生產品首次推向實用化的AA技術,也是目前nVidia GeForce 8/9系列獨享的AA技術。MSAA雖然解決了計算的問題,但存儲量還是很大,尤其是採樣率到了8以上。而CSAA就是在MSAA基礎上更進一步的節省顯存使用量及帶寬,簡單說CSAA就是將邊緣多邊形裡需要取樣的子像素坐標覆蓋掉,把原像素坐標強制安置在硬體和驅動程序預先算好的坐標中,這樣就可以用較少的color/depth空間來存儲原先高採樣數才能得到的畫質。例如圖1,我們用CSAA 16x(即16個採樣點)來渲染,就會把一個像素分成左上、右上、左下和右下4塊區域,每塊區域有4個coverage採樣點,但共享同一個color和depth。對於圖1的情況,結果就是,(0.25 * (0.885, 0.885, 1) + 0.25 * (0.885, 0.885, 1) + 3.75 * (1, 1, 0)) / 4 = (0.98, 0.98, 0.125)。性能統計:每個像素裡PS執行次數為每個覆蓋到該像素的三角形一次,佔用空間M個color + M個depth,M小於N。總之,CSAA就好比取樣標準統一的MSAA,能夠最高效率的執行邊緣取樣,效能提升也相當顯著。比方說16xCSAA取樣性能下降幅度僅比4xMSAA略高一點,效果卻幾乎和8xMSAA一樣。8xCSAA有著4xMSAA的處理效果,性能消耗卻和2xMSAA相同。
AA前世今生之:Post process AA
SSAA、MSAA和CSAA這幾種AA方法都是由硬體直接支持的,故而帶來了不小的額外資源開銷。一方面AA對顯存資源的消耗是巨大的,再者,這些AA方法對Edge(邊緣)的考量都是原始邊界,並沒有去考慮這個邊緣是否真的需要AA,故而會浪費一些計算量。在GPU Gem 2的第9章Deferred Shading in S.T.A.L.K.E.R.,其首次面向遊戲界宣傳了Deferred Shading(延遲渲染)的概念。,同時也提及了Deferred框架無法使用硬體MSAA的問題。雖然Deferred Lighting解決了其中的問題,但再次渲染一遍場景的代價還是不小的。更重要的是,由於Deferred框架的引入,人們終於開始正視MSAA實際上造成了很多時間和空間的浪費。於是乎這幾年基於Post process(後處理)的AA方法蓬勃發展,大有取代硬體式AA的氣勢。
Edge AA
Edge AA就是Deferred Shading in S.T.A.L.K.E.R提出的方法,根據「鄰居像素」的depth和normal的差異程度做一個邊緣檢測,每個像素可以得到一個權重,表示「像邊緣的程度」:
根據這個權重,就可以把鄰居像素的顏色拿來插值,得到AA的效果
在GPU Gems 3第19章Deferred Shading in Tabula Rasa中,NCsoft對Edge AA做出了一些小改進,邊緣檢測不再依賴於圖像解析度,且更加穩定。
Directionally Edge AA
Edge AA開創了post process AA的時代,但Edge AA暫時在質量上還無法與硬體式AA相抗衡。隨後,AMD在HPG09上的論文A Directionally Adaptive Edge Anti-Aliasing Filter改進了Edge AA,不再採用獨立的edge點來決定AA混合的方式,而是根據edge點周圍的狀況確定出isoline(等值線),然後根據isoline的垂直方向來確定混合的方向。這樣一個邊界就會沿著朝向來混合,還原出更加精確的sub-pixel信息。這種方法進入了AMD的驅動,只要打開Adaptive AA就會自動啟用。
MLAA(Morphological Antialiasing)形態抗鋸齒
Adaptive Edge AA提出了以線代替點的研究方向,但isoline的計算量畢竟比較大,啟用了之後對渲染性能下降明顯。Intel推出的完全基於CPU處理的抗鋸齒解決方案——Morphological Antialiasing再次在這個方向作出了努力。它不計算isoline,而是把edge分門別類,總結成Z、U、L等幾種特定的形狀,而Z和U都可以分解成L。
Z和U都可以分解成L
最終根據L劃出一個三角形,確定混合區域,這樣就省去了所有繁重的計算,提高AA速度。在AMD較新的驅動裡,MLAA取代了Directionally Edge AA成為Adaptive AA的首選。MLAA的框架又派生出多個不同的方法:
CPU MLAA
Intel在HPG09上的Morphological Antialiasing一文是在CPU上實現的。代碼用了非常深的分支來判斷edge形狀,完全是針對CPU優化的,不適合GPU硬體,也不適合實時渲染的情況。
GPU MLAA
SIGGRAPH 2010 poster的Practical morphological antialiasing on the GPU,通過建立SAT來判斷edge形狀,需要log(width)+log(height)個pass。在確定了L之後,需要查詢一個預計算的512×512 R32F的紋理,裡面每個texel對應了一個特定大小的L所需要混合的面積。也就是邊長最大是512個像素。可以看出這種方法非常暴力,雖然可能比讀回CPU快,但開銷還是很大。
Jimenez’s MLAA
GPU Pro 2裡的文章Practical Morphological Anti-Aliasing提出了一個更實用的GPU MLAA方法,命名為Jimenez’s MLAA以示區分。在這種MLAA裡,Z和U不需要分解成更簡單的L,直接用一個預計算的表來做查詢。每個像素根據自己在形狀裡的位置在查找表裡尋找需要混合的各個像素。720p的解析度下,這種方法在一般的情況下能達到Xbox 360上3.79ms,Geforce 9800 GTX+上0.44ms。同等條件下8x MSAA需要5ms。
FXAA(Fast Approximate Anti-Aliasing)
NVIDIA在Graphics SDK 11裡面提供了一個稱為Fast Approximate Anti-Aliasing的方法。該方法非常接近MLAA,但只識別長邊,而不識別形狀。有了長邊之後,就可以根據邊和像素的求交來估算每個像素中sub-pixel的覆蓋率,並進行AA混合。後來Timothy Lottes還發展出了FXAA II,質量有所下降,速度提高了,在Xbox 360上,720p的解析度可以做到2.0ms。
No AA與FXAA的對比
DLAA(Directionally Localized Anti-Aliasing)
另一個在GDC11上公開的AA方法稱為Directionally Localized Anti-Aliasing(前面介紹的Jimenez’s MLAA和FXAA也在GDC11的時候公開的)。這種方法比較特殊,它在垂直方向模糊後的圖像上做水平方向邊緣檢測,得到的結果合成回去就得到AA後的圖像。
左圖為AA之前的,右圖是經過DLAA的
DLAA的執行效率還是比較快的,據在Xbox 360上的測試來看,720p需要2.2ms。
總之:後處理式AA的方法就是試圖通過Pixel像素信息估計出Sub-pixel級別的幾何,然而再做AA。不同的是:Edge AA是通過獨立點來估計,MLAA是通過L形來估計,FXAA和DLAA是通過線段來估計。
AA前世今生之:Hybrid AA
前面我們介紹了硬體式AA和後處理式AA抗鋸齒方法,那麼有沒有將兩者結合起來的解決方案了?這正是下面要講的Hybrid AA(混合式AA)。我們先對MSAA的計算浪費這一事實進行下對比說明:
MSAA需要計算的edge
真正需要計算AA的edge
通過上面的對比圖,我們很直觀的感受到:真正需要進行AA處理的Edge邊緣其實並不是特別多,而MSAA實際上是將很多的計算量浪費在了實際並不需要AA的像素上,所以採樣點越多,浪費越嚴重。透過前面對後處理式AA的介紹,我們知道:後處理式AA的方法就是試圖通過Pixel像素信息估計出Sub-pixel級別的幾何,然而再做AA。不同的是:Edge AA是通過獨立點來估計,MLAA是通過L形來估計,FXAA和DLAA是通過線段來估計。而Hybrid AA的思想即是:乾脆就先直接存出sub-pixel的幾何,沒必要進行「估計」。
SRAA(Subpixel Reconstruction Anti-Aliasing)
SRAA是NVIDIA的研究員在I3D2011上發表的新方法。它寄予的事實是,shading的變化頻率一般低於幾何的變化頻率,所以可以在較低解析度上shading,而用較高解析度恢復幾何。SRAA的基本流程為,在Deferred Shading的框架中,渲染一個高解析度(或者帶MSAA)的G-Buffer,但在shading的時候僅在普通的解析度(或者沒有MSAA)的情況下做。累積的結果通過G-Buffer重建sub-pixel信息,來進行類似MLAA的AA計算。這種方法結合了MSAA和MLAA,優點是可以用較低的樣本數做到較高的MSAA才能得到的效果,同時不增加shading的計算量。SRAA由於原理問題,只能用在Deferred框架中。
Subpixel Reconstruction Anti-Aliasing
GPAA(Geometric Post-process Anti-Aliasing)
GPAA是Humus獨立提出來的AA方法。基本思路是在渲染幾何之後再次用線框模式渲染一遍,這時候可以得到每個三角形在每個pixel的覆蓋率:
Geometric Post-process Anti-Aliasing
通過這個覆蓋率,計算AA就顯得相當容易了,結果比較如下:
對比
這種方法的代價是多了一遍線框渲染,但可以用於Forward和Deferred兩種框架。遺憾的是,Humus的twitter上說這種方法實際上在1996年就被別人申請專利了。
Adaptive AA
Intel在SIGGRAPH 2010的course Deferred Rendering for Current and Future Rendering Pipelines上提到了一種很簡單很暴力的AA方法,在edge的地方per-sample計算,在non-edge的地方per-pixel計算。和基於post process的方法一樣,這需要執行一個邊緣檢測,並在stencil(模板)中標記出來,然後就可以分別計算了。下圖中紅線標記的地方就是檢測出來的edge:
紅線標記的地方就是檢測出來的edge
這種方法的結果會和SSAA一樣,同時沒有MSAA重複計算的毛病。
總之:Hybrid AA可以說是hardware AA 和post process AA 這兩種AA方案的折中選擇。優點是可以用低於hardware AA的硬體開銷和計算量達到一樣的效果,缺點是需要修改原有的圖形渲染流水線。
總結:AA抗鋸齒就是為了降低"方塊感"
通過前面系統的介紹,想必玩家朋友已經對AA抗鋸齒有了更深入的認識。鋸齒的產生是因為在3D圖像中,受解析度的制約,物體邊緣總會或多或少的呈現出一些不夠平滑的「稜角」,而抗鋸齒就是之通過對圖像邊緣進行柔化處理,使圖像邊緣看起來更平滑,更接近實物的物體。所以AA抗鋸齒是一種提高畫質並使之柔和的渲染方法。最後我們總結下本文的核心知識點:
一、AA抗鋸齒的作用:將圖像邊緣及其兩側的像素顏色進行混合,然後用新生成的具有混合特性的點來替換原來位置上的點以達到柔化物體外形、消除鋸齒的效果;
二、我們通常所說的幾倍抗鋸齒,指的是是一個像素點內的採樣點數;
三、AA抗鋸齒按照技術發展的演進歷程來分類有:Hardware AA、Post process AA 和Hybrid AA ;
四、Hardware AA(硬體式AA)特點:原理簡單直接,但硬體資源消耗較大。該類別的AA技術:SSAA、MSAA和CSAA等;
五、Post process AA (後處理式AA)特點:後處理式AA的方法就是試圖通過Pixel像素信息估計出Sub-pixel級別的幾何,然而再做AA。不同的是:Edge AA是通過獨立點來估計,MLAA是通過L形來估計,FXAA和DLAA是通過線段來估計。該類別的AA技術:Edge AA 、Directionally Edge AA 、MLAA和DLAA等;
六、Hybrid AA (混合式AA)特點:Hybrid AA可以說是hardware AA 和post process AA 這兩種AA方案的折中選擇。優點是可以用低於hardware AA的硬體開銷和計算量達到一樣的效果,缺點是需要修改原有的圖形渲染流水線。該類別的AA技術:SRAA 、GPAA和Adaptive AA等;
註:本文所參考的文章有:KlayGE遊戲引擎的《Anti-alias的前世今生》,建議對遊戲引擎感興趣的朋友可以去多關注下。