Unity3D Shader Stencil模版測試學習


官方文檔地址:

https://docs.unity3d.com/Manual/SL-Stencil.html

 

參考博客:

http://blog.csdn.net/onafioo/article/details/53943264

http://blog.csdn.net/u013833399/article/details/47340447

(因表述的內容都大致一樣,一些內容直接引用自原作者)

 

 

1.簡介

 

在Unity中一個像素會有多個緩存信息,模版緩存(其實Stencil不應該被翻譯成模版,但網上都這么寫)是其中之一。

模板緩沖區可以為屏幕上的每個像素點保存一個無符號整數值,

通過一些比較來改變當前像素區域模版緩沖的值,從而改變深度關系,似乎UGUI的Mask也是通過其實現的

 

 

延遲光照中Stencil有一些限制,具體看unity的文檔,這里只介紹正向光照中的使用

 

 

Stencil所在的渲染管線中的順序位置:

 

Stencil的所有參數如下

Stencil
{
    Ref 1//Reference Value
    ReadMask 255
    WriteMask 255
    Comp Always //Comparison Function
    Pass Replace
    Fail Keep
    ZFail Replace
}

 

Ref 就是參考值,當參數允許賦值時,會把參考值賦給當前像素

ReadMask 對當前參考值和已有值進行mask操作,默認值255,一般不用

WriteMask 寫入Mask操作,默認值255,一般不用

Comp 比較方法。是拿Ref參考值和當前像素緩存上的值進行比較。默認值always

  • Greater - 大於
  • GEqual - 大於等於
  • Less - 小於
  • LEqual - 小於等於
  • Equal - 等於
  • NotEqual - 不等於
  • Always - 永遠通過
  • Never - 永遠通不過

 

Pass 當模版測試和深度測試都通過時,進行處理

Fail 當模版測試和深度測試都失敗時,進行處理

ZFail 當模版測試通過而深度測試失敗時,進行處理

 

pass,Fail,ZFail都屬於Stencil操作,他們參數統一如下:

  • Keep 保持(即不把參考值賦上去,直接不管)
  • Zero 歸零
  • Replace 替換(拿參考值替代原有值)
  • IncrSat 值增加1,但不溢出,如果到255,就不再加
  • DecrSat 值減少1,但不溢出,值到0就不再減
  • Invert 反轉所有位,如果1就會變成254
  • IncrWrap 值增加1,會溢出,所以255變成0
  • DecrWrap 值減少1,會溢出,所以0變成255

 

 

2.實踐

 

下面結合案例,說一下Stencil的使用

 

現在有一個球和面片,通過Stencil模版測試把stencil值一致的物體渲染為藍色

為了更直觀使用了兩個shader,面片是shader1,球是shader2

球肯定是優先渲染,並且設置好stencil的值,面片后渲染,並且判斷stencil的值

 

文件結構:

 

MaskTest2是球的shader

Shader "Unlit/MaskTest2"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags{ "RenderType" = "Opaque" "Queue" = "Geometry" }

        Stencil
        {
            Ref 1
            Comp Always
            Pass Replace
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(1,1,1,1);
            }
            ENDCG
        }
    }
}
MaskTest2

 

Stencil里,比較條件設置為總通過,通過操作設置為替換Ref值

這樣球部分的像素Stencil值就是1

Stencil
{
    Ref 1
    Comp Always
    Pass Replace
}

 

 

MaskTest1是面片的Shader

Shader "Unlit/MaskTest1"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+1" }

        Stencil
        {
            Ref 1
            Comp equal
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(0,0,1,1);
            }
            ENDCG
        }
    }
}
View Code

 

Stencil里,比較條件是和Ref值一致時,才會執行渲染

否則跳出

Stencil
{
    Ref 1
    Comp equal
}

 

藍色是片段shader里寫好的

fixed4 frag (v2f i) : SV_Target
{
    return fixed4(0,0,1,1);
}

 

 

這樣就可以達到上述效果。

測試工程文件下載:http://files.cnblogs.com/files/hont/StencilMaskTest.zip


免責聲明!

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



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