[Shader]3D遮罩
2018-04-17 本文已影响20人
阿飞咯
Stencil
{
Ref referenceValue //参考值,这个值将用来与模板缓冲中的值进行比较。
ReadMask readMask //读取掩码,取值范围也是0-255的整数,默认值为255,二进制位11111111,即读取的时候不对referenceValue和stencilBufferValue(模板缓冲值)产生效果,读取的还是原始值
WriteMask writeMask //输出掩码,当写入模板缓冲时进行掩码操作(按位与【&】),writeMask取值范围是0-255的整数,默认值也是255,即当修改stencilBufferValue值时,写入的仍然是原始值
Comp comparisonFunction //条件,关键字有,Greater(>),GEqual(>=),Less(<),LEqual(<=),Equal(=),NotEqual(!=),Always(总是满足),Never(总是不满足)
Pass stencilOperation //条件满足后的处理
Fail stencilOperation //条件不满足后的处理
ZFail stencilOperation //深度测试失败后的处理
}
stencilOperation可用参数:
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,(然后继续自减)。
主要是使用Stencil,关于Stencil可参考
mask先渲染,将缓冲区的值设为1
Stencil{
Ref 1
Comp Always
Pass Replace
}
需要添加遮罩的后渲染,判断缓冲区的值是否为1
Stencil{
Ref 1
Comp equal
}
控制渲染顺序可以用Queue,值越小越先渲染,也可以使用Canvas设置层级
(经测试 UGUI的Mask组件也是Ref 1,同时使用可能会有冲突)
完整代码:
- mask
Shader "Unlit/3dmask"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags {
"RenderType"="Opaque"
"Queue" = "Transparent"
}
LOD 100
Stencil{
Ref 1
Comp Always
Pass Replace
}
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#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
{
return 0;
}
ENDCG
}
}
}
- Additive Mask
Shader "Unlit/Additive Mask"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags {
"RenderType"="Opaque"
"Queue" = "Transparent+1"
}
LOD 100
Stencil{
Ref 1
Comp equal
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#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
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}