Shader-StencilTest(模版測試)
阿新 • • 發佈:2018-11-15
模版測試較為複雜,它不像Alpha測試一樣,單單通過簡單的大於小於等運算子來比較,但是和Alpha測試一樣,都是測試畫素點,符合要求的就渲染,不符合要求的就不渲染。瞭解模版測試,需要理解較多術語:
1.GBuffer:幾何緩衝,相當於一個容器
2.RefenceValue:模版值,Guffer中的畫素點就是與這個值按位與後進行比較
3.stencilOperation:比較後進行的操作
4.ReadMask|WriteMask:讀遮罩|寫遮罩
理解了以上的術語,那麼模版測試的公式就差不多可以理解了:其公式為:
referenceValue&readMask comparisonFunction
如果滿足了以上公式,就會通過模版測試,反之亦然。
emmmm。。。。。博主還是感覺口說不如實踐,下面用一個穿牆透視的例子來幫助讀者理解模版測試
1.首先,在場景中新建三個Cube,並調整位置,使其分別在前,中,後三個位置,並且其大小順序為 中>前>後。
如圖所示:
2.新建三個材質與三個Shader,將三個Shader拖到三個材質上,並將三個材質分別拖到三個遊戲物體上。
3.編寫最前面遊戲物體的Shader,如下:
Shader "Hidden/StencilTestFront" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { ZWrite Off //深度測試,這裡不作解釋,不理解的可以去unity官方文件上查閱 Pass { //CompareFunction: //Greater 當GBufffer中的值大於Ref的值時才渲染(這裡指的是公式中按位與之後的結果的比較,後面都是指的這個,以後不再說明) //GEqual 當GBufffer中的值大於或者等於Ref的值時才渲染 //Less ...小於... //LEqual ...小於或者等於... //Equal ...等於... //NotEqual ...不等於... //Always 總是通過 //Never 總是不通過 //Operator: //Keep 保持GBuffer中的值不變 //Zero 將0寫入GBuffer //Replace 替換GBuffer中的值為Ref。 //IncrSat 遞增GBuffer中的值,如果該值等於255,則保持不變 //DecrSat 遞減GBuffer中的值,如果該值等於0,則保持不變 //Invert 按位取反GBuffer中的值 //IncrWrap 遞增GBuffer中的值,如果該值等於255,則變成0 //DecrWrap 遞減GBuffer中的值,如果該值等於0,則變成255 Stencil { Ref 2 //設定參考值為2 Comp always //讓模版測試總是通過 Pass replace //如果上面模版測試通過,就將GBuffer中的值替換為Ref的值 } 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; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }
4.編寫middle的Shader,程式碼如下:
Shader "Hidden/StencilTestMiddle" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // No culling or depth //Cull Off ZWrite Off ZTest Always Pass { Stencil { Ref 2 Comp NotEqual } 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; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); // just invert the colors //col.rgb = 1 - col.rgb; return col; } ENDCG } } }
5.編寫Back的Shader,程式碼如下:
Shader "Hidden/StencilTestBack"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
// No culling or depth
//Cull Off ZWrite Off ZTest Always
Pass
{
Stencil
{
Ref 2
}
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;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// just invert the colors
//col.rgb = 1 - col.rgb;
return col;
}
ENDCG
}
}
}
完成之後,即可檢視效果: