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 的部分。


        ** Stencil Test: 

                              根據對儲存在 Stencil Buffer 數值的操作,來決定是否繪製像素於螢幕上,簡單來說就是丟棄不需要的 Fragments (pixels)。下圖左為一個像素被渲染的部分流程,搭配圖右可以看出通過 Stencil Test 後還要通過 Depth Test 才會被渲染,沒通過的就會被捨棄。Stencil Buffer 的數值只是拿來當作比較的條件依據,是否會被修改則是看其他設定,如 Pass、Fail、ZFail。

        ** Unity ShaderLab: Stencil : 這個是 Unity 對 Stencil 的基本範例與說明


* Unity Stencil Syntax?

        ** 下面介紹幾個基本自己理解的。
        ** Ref referenceValue:  要拿來與 Stencil Buffer 比較的參考值 ( 0~255 ),預設 0。
        ** Comp comparsionFunction:  測試條件,預設 Always。


        ** 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 的運作

        ** 下圖共有3個物件被渲染,方塊、平面、圓球,透過對平面、圓球做 Stencil Test 達到穿透的效果,下面將一步步來解釋到底如何做到。

    1. 繪製一個圓球,當作穿透的物件

        ** 要確保圓球比板子先被繪製,這邊設定 Geometry -1、設定 ColorMask 0 代表不寫入任何顏色 ( RGBA ),關閉深度寫入,因為 ColorMask 0 所以不會有顏色,圓球目的僅使用 Stencil Test 去改變 Stencil Buffer 的數值。
        ** Ref : 比較參考值: 1
        ** Com: 測試條件: 無條件通過
        ** Pass: 測試通過操作: 參考值取代 Stencil Buffer 現有值

        ** Stencil Buffer 預設都填為 0 ,圓球繪製後,圓球的部分被改成 1 

        Queue Tag: 設定渲染佇列,數字越大越晚被渲染,相關知識 →  點我

    2. 繪製一個板子,當作被穿透的物件

        ** 板子一定要比圓球更晚繪製,這邊設定 Geometry 即可,另 Stencil Test 的條件如下,圓球部分的 Stencil Buffer 值已經被改成 1,所以板子與圓球重疊的部分就不會被繪製,達成穿透的效果。
        ** Ref : 比較參考值: 0
        ** Com: 測試條件: 參考值 = 現有值
        ** Pass: 測試通過操作: 維持 Stencil Buffer 現有值

    3. 在板子後面加上任何想繪製的物件

        ** 這步是多的....XD 我只是想看到板子被穿透後,後面的東西,這個物件我只是用預設的 Standard 材質球,繪製應該是設定在 Geometry 。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

    ** 同場加映,Stencil Box 嘗試

        ** Box 框架,每個面獨立做 Stencil Test,各填入一個數值,面不被繪製。Box 內要被繪製的物體做 Stencil Test 去對應面的 Stencil Test Ref 數值,相同的才繪製,這樣就可以達到不同面繪製不同物體的效果。Have Fun~ :)



留言

這個網誌中的熱門文章

UE4: Spine2D 導入與基本使用