模板测试 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
}
}
}
即可完成