Unity3d 超級采樣抗鋸齒 Super Sampling Anti-Aliasing


Super Sampling Anti-Aliasing
SSAA算是在眾多抗鋸齒算法中比較昂貴的一種了,年代也比較久遠,但是方法比較簡單,
主要概括為兩步
1.    查找邊緣
2.    模糊邊緣
這是一種post processing的處理方法,
接下來我們就看看怎么實現

查找邊緣

查找邊緣的原因也是因為減少消耗,這樣就可以只在邊緣處進行超級采樣,不必為全圖進行采樣了。
之前的文章詳細說過三種查找邊緣的方法Roberts,Sobel,Canny ,其中sobel最優,所以我們就是用sobel查找邊緣
這里簡單講解一下,查找邊緣的不同在於過濾器的不同,但都是水平垂直采樣
Sobel算子的兩個過濾器分別算出橫向與縱向的灰度
 
GX為水平過濾器,GY為垂直過濾器,垂直過濾器就是水平過濾器旋轉90度。
過濾器為3x3的矩陣,將與圖像作平面卷積。
如果不存在邊則兩個點顏色很接近,過濾器返回一個較小的值,否則就可判斷出邊緣的存在。
找出邊緣之后就可以模糊邊緣了

模糊邊緣

模糊邊緣就是要進行超級采樣了,采取周圍的像素點再進行混色

大家經常看到比如說SSAAx2,SSAAx4,x8….后面的數目就是采樣點的個數。

之前翻譯了一篇wiki上的超級采樣

模糊邊緣的方式(采樣方式)有很多種,比較流行的幾種有
網格采樣,隨機采樣,poisson disc采樣,Jitter算法采樣,旋轉網格采樣
 

部分方法的采樣范圍,我設定為他們邊緣的灰度了,也就是邊緣檢測中的G,因為G越大邊緣越深,出現鋸齒越明顯,就要加大采樣范圍。

我們試試網格,隨機,與旋轉采樣

網格采樣比較簡單,但是因為太規則了,模糊的效果可能不夠好,
顯獲取周圍的點,然后進行混色

		float4 c0 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.5, 1) / _Size);
				float4 c1 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.5, 1) / _Size);
				float4 c2 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.5, -1) / _Size);
				float4 c3 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.5, -1) / _Size);




然后就是隨機,個人認為隨機的效果不太好,因為像是邊緣被噪波了一樣,有像素點擴散的痕跡

				float2 randUV = 0;
				randUV = rand(float2(n.x, n.y));
				float4 c0 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size);
				randUV = rand(float2(-n.x, n.y));
				float4 c1 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size);
				randUV = rand(float2(n.x, -n.y));
				float4 c2 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size);
				randUV = rand(float2(-n.x, -n.y));
				float4 c3 = tex2D(_MainTex, i.uv_MainTex + float2(randUV.x / 2, randUV.y) / _Size);




然后就是旋轉網格采樣,最佳的旋轉角度是arctan (1/2) (大約 26.6°),這里偷個懶,也省去了旋轉計算的消耗,大概個位置進行采樣,效果還算好。

		<span style="font-size:14px;">		float4 c0 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.2 / 2, 0.8) / _Size);
				float4 c1 = tex2D(_MainTex, i.uv_MainTex + fixed2(0.8 / 2, -0.2) / _Size);
				float4 c2 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.2 / 2, -0.8) / _Size);
				float4 c3 = tex2D(_MainTex, i.uv_MainTex + fixed2(-0.8 / 2, 0.2) / _Size);</span>

結果比較

 

 

 

性能

性能方面SSAA比其他AA弱了一些,主要因為方法是這樣暴力的采樣

SSAA采樣方式間的損耗都差不多

都是SSAAx4

無抗鋸齒


網格采樣


隨機采樣

旋轉采樣

 

在unity中image effect的SSAA消耗與本文差不多

又看了一下其他的unity的抗鋸齒方法,發現FXAA消耗是最少的在2.8ms左右

 

全部代碼已共享至GitHub

 

                             ----- by wolf96

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM