Shader Stencil Buffer and Stencil Test
Stencil Buffer ( 模版緩衝空間 ),白話文就是一個 2 維度存放資料的記憶體空間....XD,這個空間內存放的數值可以拿來做 Stencil Test ( 模版測試 ),透過 Stencil Test 可以做到一些效果。
* Stencil Buffer 的應用?
** 老實說,我自己覺得當理解了 Stencil 後會發現,原理好像沒這麼難,但要想到可以應用在哪,反而是比較困難的。所以特別找了更多應用範例,也是網路上各位大大分享的,附上效果與連結。
Stencil Effect -- Joyce[MinionsArt] |
* Stencil Buffer 是什麼,Stencil Test 如何運作?
** Stencil Buffer:
一個 2 維度的記憶體空間 (緩/暫存區),類似 Color Buffer / Depth Buffer,但 Stencil 儲存的不是浮點數而是整數,最大值 0xFF ( 0~255 ),使用位元運算。下圖中顯示 Stencil Buffer 儲存預設值為 0,貼著貼圖的 Box透過 Stencil Test 對 Stencil Buffer 修改並渲染/繪製數值 1 的部分。
一個 2 維度的記憶體空間 (緩/暫存區),類似 Color Buffer / Depth Buffer,但 Stencil 儲存的不是浮點數而是整數,最大值 0xFF ( 0~255 ),使用位元運算。下圖中顯示 Stencil Buffer 儲存預設值為 0,貼著貼圖的 Box透過 Stencil Test 對 Stencil Buffer 修改並渲染/繪製數值 1 的部分。
** Stencil Test:
** Pass stencilOperation: 設置像素若通過 Stencil Test 與 Depth Test 的 Stencil Buffer 操作,預設 Keep。
** Fail stencilOperation: 設置像素若沒通過 Stencil Test 的 Stencil Buffer 操作,預設 Keep。
** ZFail stencilOperation: 設置像素若通過 Stencil Test,但沒通過 Depth Test 的 Stencil Buffer 操作,預設 Keep。
根據對儲存在 Stencil Buffer 數值的操作,來決定是否繪製像素於螢幕上,簡單來說就是丟棄不需要的 Fragments (pixels)。下圖左為一個像素被渲染的部分流程,搭配圖右可以看出通過 Stencil Test 後還要通過 Depth Test 才會被渲染,沒通過的就會被捨棄。Stencil Buffer 的數值只是拿來當作比較的條件依據,是否會被修改則是看其他設定,如 Pass、Fail、ZFail。
** Unity ShaderLab: Stencil : 這個是 Unity 對 Stencil 的基本範例與說明
** Comp comparsionFunction: 測試條件,預設 Always。** Unity ShaderLab: Stencil : 這個是 Unity 對 Stencil 的基本範例與說明
* Unity Stencil Syntax?
** 下面介紹幾個基本自己理解的。
** Ref referenceValue: 要拿來與 Stencil Buffer 比較的參考值 ( 0~255 ),預設 0。
** Ref referenceValue: 要拿來與 Stencil Buffer 比較的參考值 ( 0~255 ),預設 0。
** Fail stencilOperation: 設置像素若沒通過 Stencil Test 的 Stencil Buffer 操作,預設 Keep。
** ZFail stencilOperation: 設置像素若通過 Stencil Test,但沒通過 Depth Test 的 Stencil Buffer 操作,預設 Keep。
* 簡單的範例來解釋 Stencil 的運作
** 下圖共有3個物件被渲染,方塊、平面、圓球,透過對平面、圓球做 Stencil Test 達到穿透的效果,下面將一步步來解釋到底如何做到。
1. 繪製一個圓球,當作穿透的物件
** 要確保圓球比板子先被繪製,這邊設定 Geometry -1、設定 ColorMask 0 代表不寫入任何顏色 ( RGBA ),關閉深度寫入,因為 ColorMask 0 所以不會有顏色,圓球目的僅使用 Stencil Test 去改變 Stencil Buffer 的數值。
** Ref : 比較參考值: 1
** Com: 測試條件: 無條件通過
** Pass: 測試通過操作: 參考值取代 Stencil Buffer 現有值
Queue Tag: 設定渲染佇列,數字越大越晚被渲染,相關知識 → 點我
** Ref : 比較參考值: 1
** Com: 測試條件: 無條件通過
** Pass: 測試通過操作: 參考值取代 Stencil Buffer 現有值
** Stencil Buffer 預設都填為 0 ,圓球繪製後,圓球的部分被改成 1
2. 繪製一個板子,當作被穿透的物件
** 板子一定要比圓球更晚繪製,這邊設定 Geometry 即可,另 Stencil Test 的條件如下,圓球部分的 Stencil Buffer 值已經被改成 1,所以板子與圓球重疊的部分就不會被繪製,達成穿透的效果。
** Ref : 比較參考值: 0
** Com: 測試條件: 參考值 = 現有值
** Pass: 測試通過操作: 維持 Stencil Buffer 現有值
** Com: 測試條件: 參考值 = 現有值
** Pass: 測試通過操作: 維持 Stencil Buffer 現有值
3. 在板子後面加上任何想繪製的物件
** 這步是多的....XD 我只是想看到板子被穿透後,後面的東西,這個物件我只是用預設的 Standard 材質球,繪製應該是設定在 Geometry 。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
** 同場加映,Stencil Box 嘗試
** Box 框架,每個面獨立做 Stencil Test,各填入一個數值,面不被繪製。Box 內要被繪製的物體做 Stencil Test 去對應面的 Stencil Test Ref 數值,相同的才繪製,這樣就可以達到不同面繪製不同物體的效果。Have Fun~ :)
留言
張貼留言