unity ShaderLab 基础之【模板测试 StencilTest】StencilTest命令详解

模板测试 StencilTest

啥是模板测试,每个像素都有一个stencil值,在同一个像素上,所有shader的stencil都共享这一个值,当有其他带有遮罩像素与其重合时就能获取到该值,并根据自身的stencil值处理或。典型的应用就是遮罩显示。你可以选择每次重合都增加1,然后再指定某个物体,当值达到某个数量级再显示。这样的场景,比如,有个隐身的怪物,你只有使用圣水喷雾才能让他现行,但必须喷3次才行,这样,空中就存在了3次叠加的雾,透过这个3层雾就能看到怪物了。但你偏一下角度,透过两层wu就看不到。
Stencil完整语法:

stencil{
	Ref referenceValue //每个像素都有一个stencil值,在同一个像素上,所有shader的stencil都共享这一个值,当有其他带有遮罩像素与其重合时就能获取到该值,并根据自身的stencil值处理触发小狗
	ReadMask  readMask  //读遮罩
	WriteMask writeMask  //写遮罩
	Comp comparisonFunction   //条件判断  大于小于等触发
	Pass stencilOperation    //满足条件后,相应的处理办法   是替换值还是增长值等
	Fail stencilOperation    //没有通过模板测试怎么办
	ZFail stencilOperation    //通过了模板测试怎么办
}

模板语法

参数 说明 实例
Ref ref用来设定参考值(范围0-255)。这个值用来与stencilbuffer比较
ReadMask ReadMask 从字面意思的理解就是读遮罩,readMask将和referenceValue以及stencilBufferValue进行按位与(&)操作,readMask取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue产生效果,读取的还是原始值
WriteMask WriteMask是当写入模板缓冲时进行掩码操作(按位与【&】),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值。
Comp Comp是定义参考值(referenceValue)与缓冲值(stencilBufferValue)比较的操作函数,默认值:always
Pass Pass是定义当模板测试(和深度测试)通过时,则根据(stencilOperation值)对模板缓冲值(stencilBufferValue)进行处理,默认值:keep
Fail Fail是定义当模板测试(和深度测试)失败时,则根据(stencilOperation值)对模板缓冲值(stencilBufferValue)进行处理,默认值:keep
ZFail ZFail是定义当模板测试通过而深度测试失败时,则根据(stencilOperation值)对模板缓冲值(stencilBufferValue)进行处理,默认值:keep

模板对比

指令 说明 实例
Greater 大于,只渲染大于该值的像素。 alphatest greater [_alphaValue] //类似于抠图
Less 小于,只渲染小于该值的像素。 类似于反向抠图
GEqual 大于等于
LEqual 小于等于
Equal 等于
NotEqual 不等于
Always 总是
Never 永不
Off 关闭 alphatest Off

模板操作

指令 说明 实例
Keep 保留当前缓冲中的内容,即stencilBufferValue不变
Zero 将0写入缓冲,即stencilBufferValue值变为0。
Replace 将参考值写入缓冲,即将referenceValue赋值给stencilBufferValue。
IncrSat stencilBufferValue加1,如果stencilBufferValue超过255了,那么保留为255,即不大于255。
DecrSat stencilBufferValue减1,如果stencilBufferValue超过为0,那么保留为0,即不小于0。
Invert 将当前模板缓冲值(stencilBufferValue)按位取反
IncrWrap 当前缓冲的值加1,如果缓冲值超过255了,那么变成0,(然后继续自增)
DecrWrap 当前缓冲的值减1,如果缓冲值已经为0,那么变成255,(然后继续自减) 。

实例:遮罩
将此shader付给遮罩物体

Shader "Custom/st1" {
	SubShader{
		Tags { "RenderType" = "Opaque" "Queue" = "Geometry-1"}
			CGINCLUDE
				struct appdata {
					float4 vertex : POSITION;
				};
				struct v2f {
					float4 pos : SV_POSITION;
				};
				v2f vert(appdata v) {
					v2f o;
					o.pos = UnityObjectToClipPos(v.vertex);
					return o;
				}
				half4 frag(v2f i) : SV_Target {
					return half4(1,1,0,1);
				}
			ENDCG
			Pass {
				ColorMask 0
				ZWrite Off
				Stencil
				{
					Ref 1
					Comp Always
					Pass Replace
				}
				CGPROGRAM
					#pragma vertex vert
					#pragma fragment frag
				ENDCG
			}
	}
}

将此shader付给被遮罩物体

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'


Shader "Custom/st2" {
	Properties{
	_MainTex("Base (RGB)", 2D) = "white" {}
	}
		SubShader{
			Tags { "Queue" = "Geometry" "RenderType" = "Opaque" }
			LOD 100
			Pass {
				Stencil
				{
					Ref 2
					Comp Equal
				}
				CGPROGRAM
					#pragma vertex vert
					#pragma fragment frag
					#pragma multi_compile_fog
					#include "UnityCG.cginc"
					struct appdata_t {
						float4 vertex : POSITION;
						float2 texcoord : TEXCOORD0;
					};
					struct v2f {
						float4 vertex : SV_POSITION;
						half2 texcoord : TEXCOORD0;
						UNITY_FOG_COORDS(1)
					};
					sampler2D _MainTex;
					float4 _MainTex_ST;
					v2f vert(appdata_t v)
					{
						v2f o;
						o.vertex = UnityObjectToClipPos(v.vertex);
						o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
						UNITY_TRANSFER_FOG(o,o.vertex);
						return o;
					}
					fixed4 frag(v2f i) : SV_Target
					{
						fixed4 col = tex2D(_MainTex, i.texcoord);
						UNITY_APPLY_FOG(i.fogCoord, col);
						UNITY_OPAQUE_ALPHA(col.a);
						return col;
					}
				ENDCG
			}
	}
}

即可完成

发布了139 篇原创文章 · 获赞 37 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/lengyoumo/article/details/104231133