全屏反鋸齒 - 多重採樣Ⅰ

圖形繪製的時候總能看見那些不美觀的鋸齒。尤其是邊緣鋸齒給用戶帶來的突兀感,給了計算機圖形學幾乎一個屬於“領域”的研究——反鋸齒。視覺上的美觀優化,以及改進後的運行效率,兩手都要硬。——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

發佈了54 篇原創文章 · 獲贊 13 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章