Unity Shader之模板測試
一沙一世界,一花一天堂html
1、Stencil testing
渲染管線
當片斷着色器處理完一個片斷以後,模板測試(Stencil Test)會開始執行,和深度測試同樣,它也可能會丟棄片斷。接下來,被保留的片斷會進入深度測試,它可能會丟棄更多的片斷。模板測試是根據又一個緩衝來進行的,它叫作模板緩衝(Stencil Buffer),咱們能夠在渲染的時候更新它來得到一些頗有意思的效果。
一個模板緩衝中,(一般)每一個模板值(Stencil Value)是8位的。因此每一個像素/片斷一共能有256種不一樣的模板值。咱們能夠將這些模板值設置爲咱們想要的值,而後當某一個片斷有某一個模板值的時候,咱們就能夠選擇丟棄或是保留這個片斷了。
2、模板函數
2.1 調用函數
- Stencil
- {
- Ref 1
- Fail Keep
- ZFail Replace
- }
2.2 參數說明
Ref :就是參考值,當參數容許賦值時,會把參考值賦給當前像素
ReadMask: 對當前參考值和已有值進行mask操做,默認值255,通常不用
WriteMask: 寫入Mask操做,默認值255,通常不用編程
Comp: 比較方法。是拿Ref參考值和當前像素緩存上的值進行比較。默認值always,即一直經過。
-- Greater - 大於api
- GEqual - 大於等於
- Less - 小於
- LEqual - 小於等於
- Equal - 等於
- NotEqual - 不等於
- Always - 永遠經過
- Never - 永遠通不過
Pass: 當模版測試和深度測試都經過時,進行處理緩存
Fail :當模版測試和深度測試都失敗時,進行處理app
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
3、案例
3.1 描邊
渲染管線
- Shader "ShaderCookbook/stencil_outline" {
- Properties {
- _MainTex("Texture", 2D) = "white" {}
- _OutLineWidth("Width", float) = 0.01
- _OutLineColor("Color", color) = (1, 1, 1, 1)
- }
- SubShader {
- Tags {
- "RenderType" = "Opaque"
- }
- LOD 100
-
- Stencil {
- Ref 0 Comp Equal Pass IncrSat
- }
-
- 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 {
-
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
-
- Pass {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- struct appdata {
- float4 vertex: POSITION;
- float4 normal: NORMAL;
- };
-
- struct v2f {
- float4 vertex: SV_POSITION;
- };
-
- fixed4 _OutLineColor;
- float _OutLineWidth;
- v2f vert(appdata v) {
- v2f o;
- v.vertex = v.vertex + normalize(v.normal) * _OutLineWidth;
- o.vertex = UnityObjectToClipPos(v.vertex);
- return o;
- }
- fixed4 frag(v2f i) : SV_Target {
-
- fixed4 col = _OutLineColor;
- return col;
- }
- ENDCG
- }
- }
- }
3.2 百寶箱
渲染管線
遮罩層:工具
- Shader "ShaderCookbook/StencilEnumMask"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- [ForceInt]
- _StencilRef("StencilRef",float) = 0
- [Enum(UnityEngine.Rendering.CompareFunction)]
- _StencilComp("StencilComp",int) =0
- [Enum(UnityEngine.Rendering.StencilOp)]
- _StencilOp("StencilOp",int)=0
-
- [ForceInt]
- _StencilReadMask("ReadMask",int)=255
- [ForceInt]
- _StencilWriteMask("WriteMask",int)=255
- [MaterialToggle]
- _ZWrite("zWrite",float)=0
- }
- SubShader
- {
- Tags { "RenderType"="StencilMaskOpaque"
- "Queue" = "Geometry-100"
- "IgnoreProjector" = "True" }
- LOD 100
-
-
- Pass
- {
- ColorMask 0
- ZWrite [_ZWrite]
-
- Stencil{
- Ref [_StencilRef]
- Comp[_StencilComp]
- Pass[_StencilOp]
- ReadMask[_StencilReadMask]
- WriteMask[_StencilWriteMask]
- }
-
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fog
- #include "UnityCG.cginc"
-
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- UNITY_FOG_COORDS(1)
- 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);
- UNITY_TRANSFER_FOG(o,o.vertex);
- return o;
- }
- fixed4 frag (v2f i) : SV_Target
- {
-
- fixed4 col = tex2D(_MainTex, i.uv);
-
- UNITY_APPLY_FOG(i.fogCoord, col);
- return col;
- }
- ENDCG
- }
- }
- }
顯示層:測試
-
-
- Shader "ShaderCookbook/StencilEnum"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- [ForceInt]
- _StencilRef("StencilRef",float) = 0
- [Enum(UnityEngine.Rendering.CompareFunction)]
- _StencilComp("StencilComp",int) =0
- [Enum(UnityEngine.Rendering.StencilOp)]
- _StencilOp("StencilOp",int)=0
-
- [ForceInt]
- _StencilReadMask("ReadMask",int)=255
- [ForceInt]
- _StencilWriteMask("WriteMask",int)=255
- }
- SubShader
- {
- Tags { "RenderType"="opaque" }
- LOD 100
-
-
- Pass
- {
-
- Stencil{
- Ref [_StencilRef]
- Comp[_StencilComp]
- Pass[_StencilOp]
- ReadMask[_StencilReadMask]
- WriteMask[_StencilWriteMask]
- }
-
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fog
- #include "UnityCG.cginc"
-
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- UNITY_FOG_COORDS(1)
- 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);
- UNITY_TRANSFER_FOG(o,o.vertex);
- return o;
- }
- fixed4 frag (v2f i) : SV_Target
- {
-
- fixed4 col = tex2D(_MainTex, i.uv);
-
- UNITY_APPLY_FOG(i.fogCoord, col);
- return col;
- }
- ENDCG
- }
- }
- }
Ad
這裏推薦一款可視化shader編程工具,對美術同窗很是友好,就像建模工具中的材質編輯器同樣ui