OpenGL之模板測試


模板測試與深度測試類似,但在渲染管線中發生在深度測試之前。模板測試也會丟棄掉一些片段,只是丟棄的片段數量比深度測試少。

同時該測試也是基於另一個緩沖區 --- 模板緩沖區(stencil buffer),同理該緩沖區也是由我們創建窗口庫創建的,我使用的庫是GLFW庫。該模板緩沖區中的模板值大小為8位所以每個像素有256種不同的模板值,就好比RGBA每一個中顏色有256 = 2^8種,所以總的大小為32 位.所以我們就根據模板值來決定是否丟棄或保留。

模板測試例子:

首先要使用模板測試,必須先開啟glEnable(GL_STENCIL_TEST),然后清除上一幀的模板緩沖glClear(GL_STENCIL_BUFFER_BIT)設置所有片段的模板值為0,然后開啟矩形片段用1填充。場景中的模板值為1的那些片段才會被渲染,其他的都被丟棄。

 

使用模板緩沖的過程:

  • 開啟模板緩沖寫入。glEnable(GL_STENCIL_TEST)
  • 渲染物體,更新模板緩沖。模板緩沖函數后面介紹
  • 關閉模板緩沖寫入。glDisable(GL_STENCIL_TEST)
  • 渲染(其他)物體,這次基於模板緩沖內容丟棄特定片段。

模板緩沖的寫入:

與深度測試函數管理glDepthMask()相似,模板緩沖有個函數glStencilMask()來設置是否可以對緩沖區進行寫入,其原理是給模板值設置一個位遮罩(Bitmask),它與模板值進行按位與(and)運算決定緩沖是否可寫。默認參數設置的位遮罩是0xFF(1),這樣就不會影響輸出,但是如果我們設置為0x00,所有寫入深度緩沖最后都是0,說明模板緩沖區不可寫入

 

 配置模板測試函數:

   void glStencilFunc(GLenum func, GLint ref, GLuint mask)函數有三個參數:

  • func:設置模板測試操作。這個測試操作應用到已經儲存的模板值和glStencilFuncref值上即判斷模板測試通過的條件,例如我func設置為GL_EQUAL,ref為1,那么模板測試通過的條件就是模板值等於1,可用的選項是:GL_NEVERGL_LEQUALGL_GREATERGL_GEQUALGL_EQUALGL_NOTEQUALGL_ALWAYS,它們的語義和深度緩沖的相似。
  • ref:指定模板測試的引用值。模板值會與這個值按func方式進行對比。
  • mask:指定一個遮罩,在 模板測試 對比  引用值ref和儲存的模板值  前,對它們進行按位與(and)操作,初始設置為1。

      glStencilFunc只描述了OpenGL對模板緩沖做什么,而不是描述我們如何更新緩沖區,此時就出現了glStencilOp()

   void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)函數包含三個選項,我們可以指定每個選項的動作:

  • sfail: 如果模板測試失敗將采取的動作。
  • dpfail: 如果模板測試通過,但是深度測試失敗時采取的動作。
  • dppass: 如果深度測試和模板測試都通過,將采取的動作。(此處有點迷惑就是深度測試不是發生在模板測試之后嗎,為什么會出現這個選項)

     glStencilOp函數默認設置為 (GL_KEEP, GL_KEEP, GL_KEEP) ,所以任何測試的任何結果,模板緩沖都會保留它的值。總之使用glStencilFuncglStencilOp,我們就可以指定在什么時候以及我們打算怎么樣去更新模板緩沖了,我們也可以指定何時讓測試通過或不通過。

 

 

模板測試的應用:制作物體的輪廓(就好比在策略游戲中鼠標點擊的物體身邊會出現光圈)

具體的步驟如下:

  1. 在繪制物體前,把模板方程設置為GL_ALWAYS,用1更新物體將被渲染的片段。//使用glStencilOp選項中的GL_REPLACE將模板值設置成glStencilFunc中的ref值
  2. 渲染物體,寫入模板緩沖。
  3. 關閉模板寫入和深度測試。
  4. 每個物體放大一點點。
  5. 使用一個不同的片段着色器用來輸出一個純顏色。
  6. 再次繪制物體,但只是當它們的片段的模板值不為1時才進行。
  7. 開啟模板寫入和深度測試。

代碼如下:

代碼分析:
1.首先開啟模板測試

2.如果任何測試失敗我們值保持深度緩沖中當前所儲存着的值。如果模板測試和深度測試都成功了,我們就將儲存着的模板值替換為1,我們要用glStencilFunc(等到該函數執行時還功能才實現)來做這件事。

3.清楚上一幀的顏色緩沖,深度緩沖,模板緩沖值

4.繪制地板時禁止對模板緩沖的寫入

5,6.繪制地板

7.設置模板測試都能通過,且ref為1即將模板緩沖區值設置成1

8.設置模板緩沖區是可寫入的

9.繪制兩個容器

10.我們把模板方程設置為GL_NOTEQUAL,它保證我們只箱子上不等於1的部分,這樣只繪制前面繪制的箱子外圍的那部分

11.注意,我們也要關閉深度測試,這樣放大的的箱子也就是邊框才不會被地面覆蓋

12.再次開啟深度緩沖。


免責聲明!

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



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