圖形繪製的時候總能看見那些不美觀的鋸齒。尤其是邊緣鋸齒給用戶帶來的突兀感,給了計算機圖形學幾乎一個屬於“領域”的研究——反鋸齒。視覺上的美觀優化,以及改進後的運行效率,兩手都要硬。——ZwqXin.com
本文來源於 ZwqXin (http://www.zwqxin.com/),
轉載請註明
原文地址:http://www.zwqxin.com/archives/opengl/antialiasing-multi-sample-1.html
鋸齒是由於屏幕分辨率低所造成的贗項,想必大家也知道這指什麼。CSDN裏一位高人仁兄問道,在顯卡設置裏面有所謂的“反鋸齒”選項,可以設置覆蓋採樣的參數,那麼在OpenGL裏是否也有相應的API能夠做相應的設置呢?我剛開始是認爲所謂顯卡里的抗鋸齒是shader裏對屏幕做全屏PCF(百分比漸進過濾),而OPENGL的API裏面也沒見過有什麼可以接收類似覆蓋採樣這樣的參數的,頂多是glHint那類函數可以通過混合等緩解點線的鋸齒現象罷了。可接下來有人回帖說了NEHE46課,我馬上“覺醒”,對喔,NEHE裏[蒐集的優良OpenGL教程] 確實有課叫什麼“全屏反鋸齒”的,馬上在電腦裏找出來看——還真的有呢!
所謂採樣參數,也可以說是“平滑處理級別”,一般就有1X,2X,4X,8X,16X這幾個值。在[圖像處理裏的空間域濾波] 一文中,談到了圖像的平滑處理(模糊),其本質就是通過把一個像素作鄰域處理(領域加合平均)得出新像素值而已,領域大小被稱爲模板參數,一般是個奇數,這樣才能把待處理像素包圍在中間。而這裏的採樣參數,乍一看就是2的N次方這樣的數,但竊認爲其實都是那麼回事,只不過更適合於描述而已。
通常認爲在實時圖形學中,這種像素級別的操作應該交給強大的Shder。在shader裏被稱爲dithered samples的,就是PCF係數。因爲它的可編程性能,對顯卡的要求就更可具彈性了,實際上任何X都可以,不限制於2的N次方。
爲了說得清晰點,以橙書裏關於對Shadow map做PCF那章的代碼段爲例(ZwqXin也弄過[Shadow Map陰影貼圖技術之探Ⅲ] ):
//Listing 13.7. Fragment shader for generating shadows, using four dithered samples
uniform sampler2DShadow ShadowMap;
uniform float Epsilon;
uniform bool SelfShadowed;
uniform float SelfShadowedVal;
uniform float NonSelfShadowedVal;
varying vec3 ShadowCoord;
float Illumination;
float lookup(float x, float y)
{
float depth = shadow2D(ShadowMap,
ShadowCoord + vec2(x, y) * Epsilon).x;
return depth != 1.0 ? Illumination : 1.0;
}
void main()
{
// lighten up the self-shadows
Illumination = SelfShadowed ? SelfShadowedVal : NonSelfShadowedVal;
// use modulo to vary the sample pattern
vec2 o = mod(floor(gl_FragCoord.xy), 2.0);
float sum = 0.0;
sum += lookup(vec2(-1.5, 1.5) + o);
sum += lookup(vec2( 0.5, 1.5) + o);
sum += lookup(vec2(-1.5, -0.5) + o);
sum += lookup(vec2( 0.5, -0.5) + o);
gl_FragColor = vec4(sum * 0.25 * gl_Color.rgb, gl_Color.a);
}
這裏你可以認爲是爲了消緩shadow map形成的鋸齒而做的“全屏反鋸齒”,或者說“全屏模糊化”“全屏平滑化”(針對陰影帖圖覆蓋之場景)。參數是4X。看最下面幾行,它做了一些檢索紋理(陰影圖)的動作。sum是個顏色計數器,它把當前處理像素所在紋素的周邊四個紋素的值相加,並在輸出時除以4以歸一化回[0,1]區間——這是典型的模板濾波操作。當然還有一點小動作(取非整值並根據紋理索引的奇偶再偏移0個或1個紋素),不多提,但總體思路就是這樣——這就是PCF的雛形。一張紋理的顏色過渡只有在邊緣處鉅變,而人眼對邊緣的部分總是比較敏感,邊緣處產生的模糊正能消除這種突兀感。
好吧,如果這算4X,那麼5X,6X如此下去都可以。但是4X和5X你能想到兩者有啥區別麼?無非後者多攪和了一個紋素而已,如果這個被攪和的紋素不用中心紋素,你還得決定是在哪個方向多加一個呢!6X就更不用說了.......所以說,下一個“級別”應該是關於中心紋素得包圍圈向外延伸一個紋素,每方向上加多一個,也就是8X了.......如此類推,你能發現比較勻稱和諧的“採樣參數”都是2的N次方。
另一方面,總不能無限地32X,64X下去吧,要知道,每多一個“級別”,對每個像素就得做多一倍的加法,運算效率下來了,這還不算,更主要的是,整張紋理都被錯位疊加N次了,紋理被覆物最後真被模糊得血肉模糊,不成人形(喂,本來就不成嘛)了——因爲平滑模糊,就相當於去處細節!
概念講到這裏,回到開頭那裏。顯卡里的PCF?我看了看自己的顯卡的控制面板(NV9),裏面解釋到:
平滑處理可設置爲有利於提高系統性能或改進圖象質量。
-
如果要顯示三維動畫效果和強調場景的流暢變換,最好使用性能設置。
-
如果要以顯示非常精細和逼真的三維物體爲主要目的時,最好使用質量設置。
-
在“管理 3D 設置”頁面上(高級視圖),您可以設置具體的平滑處理級別。
值越高,對應的平滑處理的級別就越高。例如,16x 的質量要高於 2x。
在 GeForce 8 系列 GPU 中,NVIDIA 推出了一種新形式的平滑處理,稱爲“覆蓋採樣”,該功能對 8x、16x 和 16xQ 平滑處理設置產生影響。如需更多信息,請參照 NVIDIA.com 網站上關於 Lumenex 引擎技術的簡介。
-
如果您不能肯定如何配置平滑處理,請使用“應用程序控制的”選項。您的顯示將根據應用程序的規定自行調整。
有粗略的設置方法(質量-效率權衡):
也有可能做個精確一點的設置:
的確是可以設置的。那麼,既然顯卡提供了這樣的功能,那麼有對應的集成API也很正常吧。但是,看完NEHE46課後,我知道OPenGL裏能實現這種設置的方法是使用一個叫"multi sample"的擴展。而且也不能一步到位,需要設置不少東西。我不能肯定它與PCF有沒有什麼特別的聯繫,於是我想自己按照NEHE 46來實現一下。
請留意下篇文章:全屏反鋸齒 - 多重採樣Ⅱ
本文來源於 ZwqXin (http://www.zwqxin.com/),
轉載請註明
原文地址:http://www.zwqxin.com/archives/opengl/antialiasing-multi-sample-1.html