使用模板模板緩衝時需要注意的幾個問題
-----作者: 熊 斌 2007.12.30 xiongbincsu@yahoo.com.cn
也許你使用過樣板緩衝區,但是你真正懂得它的正確用法嗎?
本人根據實踐總結出下面幾個問題,希望對大家能有所協助:
1. 使用樣板緩衝區的步驟
2.glStencilFunc中的參數意義,及如何選擇合理參數?
3.glStencilOp中的參數意義及選用.
====================================================================
問題1:
簡而言之:
1)指定預設範本值,用其清除樣板緩衝區,
2)開啟模板測試功能, 指定模板比較函數, 指定模板測試失敗後對相應位置的模板值的操作方式.
3)用繪圖命令繪製一個模板圖形
4) 繪製其他圖形
下面詳細敘述:
如果你要使用一個樣板緩衝區,那麼首先你要在使用之前象清除顏色緩衝區一樣,把原來緩衝區裡的無效資料給清理乾淨,這就是在調用glClear() 時 加上GL_STENCIL_BUFFER_BIT. 也就是象這樣:
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
與顏色緩衝區類似,你在使用這個函數之前也要指定一個預設填儲值, 你可以這樣指定 glClearStencil(0);
當然你不一定要用0,就像你清除顏色緩衝區時不一定要指定glClearColor(0,0,0).一樣,你要根據你的需要來設定.
設定好預設值後,並用這個預設值將模板樣板緩衝區填滿以後,你就可以在你需要的地方開始使用它了:
glEnable(GL_STENCIL_TEST);
接下來我們要產生我們的模板,實際上就是通過一組繪圖命令,來繪出一個映像,把它當作模板. 比如我們要產生一個鏤空的花窗,那麼我們可以把這個花窗需要空的部分繪出來,當作模板,使得在進行後續繪圖時,落到這個模板上的映像不被繪製,就形成了鏤空.. 好了,扯遠了, 這隻是告訴你什麼叫模板....... 呵呵,好像沒這個必要???
因為我們在創造我們的模板時使用的也是繪圖命令,有時候,我們並不想讓這個模板本身被別人看見, (一個圖形要被看見 等於 它被寫入顏色緩衝並最終被交換到螢幕上來)..為了不讓這些建立模板的代碼被顯示為圖形,我們需要禁止顏色緩衝的寫入, 這可以通過下面的語句做到
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); 它使所有的色彩通道都不可以寫入
同理,如果我們不希望繪製模板的代碼影響深度緩衝區,那麼我們可以調用 glDisable(GL_DEPTH_TEST); 來禁止深度緩衝的寫入.
設定好這些後,我們準備開始繪製模板,
繪製模板之前, 我們需要給模板本身所繪製的圖形指定一個模板值,為什麼呢? 因為模板測試類別似與深度測試, 它是通過把已有的樣板緩衝區的值,與將要繪製的圖形的模板值相比較,然後只繪製使得比較結果為真的那些映像...
現在樣板緩衝區裡面全是預設值,那麼我們需要給模板本身指定一個值,那麼在以後進行繪製時,就可以拿要繪製的映像的模板值與這個值做比較從而進行取捨了...
而怎麼樣給繪製的映像賦上模板值,並進行比較呢? 這就是通過2,3 問題中所述的兩個函數來進行, 請接著往下看...
問題2. glStencilFunc 用法
glStencilFunc的原形是: glStencilFunc( GLenum func, GLint ref, GLuint mask);
它的作用就是來指定 模板測試 的比較函數, 這些函數用來將 "當前繪製映像的模板值" 與 "要寫入位置的模板值" 進行比較 以得到一個Ture Or False 值 , 這個比較函數由第一個參數指定,它是一個 枚舉值,可選的有 GL_GREATER ,GL_LESS 等, 第二個就是緊跟著這個函數的繪圖函數所繪圖形,的模板值, 它用來與要繪製的目標位置的模板值,用第一個參數指定的函數進行比較,得到結果.. 但是這種比較並不是直接拿這兩個值去比, 假如要繪製的目標位置的模板值是B,第二個參數指定的是A, 那麼比較是這樣進行的, 先將 A與第三個參數 mask 進行AND操作 並同時將 B與mask 進行與操作,然後按指定的比較函數func比較結果 ,
也就是 ((ref & mask) op (svalue & mask))
如果A 與B的比較結構為真,則寫入,假則不寫入...
問題3: glStencilOp用法
glStencilOp() 函數的原形為: glStencilOp(GLenum fail , GLenum zfail, GLenum zPss );
它的作用是用來指定,當某些圖元在繪製的時候,如果模板測試失敗(或者深度測試失敗),它怎麼修改其打算寫入的位置的模板值. 它的三個參數 分別指定了,當模板測試失敗了 該如何修改, 深度測試失敗了如何修改,以及 深度測試如果成功又該怎麼修改.... 後面兩個參數也就是說,就算模板測試通過,我們也可以通過深度測試的測試結果修改模板值..
它們的可選值為: GL_KEEP(保持不變), GL_DEC(減少) , GL_INCR(增加) ,GL_REPLACE(替換),
特別需要注意的是: 這些操作在每個面片被寫入的時候都會進行,如果你使用GL_INCR , 可能你只繪製了一個模型,但是,這個模型有幾個面片在深度上重疊,那麼在每次寫入這些面片時,都會引起一次GL_INCR, 也就是模板值 +1 , 如果你不曾注意到這個問題,那麼你在測試函數glStencilFunc 中時選用 GL_EQUAL 就會得到不正確的結果.. 如果你需要使用GL_EQUAL 建議你在本函數中選用 GL_REPLACE ,這個變數引起函數用 glStencilFunc 中指定的 ref 值來替代 當前要繪製位置的模板值, 這樣多次操作不會有影響....