一、原理
遮罩shader的原理其实就是乘法运算
color * 1 = color
color * 0 = 0
在计算机程序语言表达颜色的时候,(1,1,1,1)表示白色和不透明,(0,0,0,0)表示黑色和完全透明
比如我们将color贴图和mask贴图(白色背景的可能看不见,可以点击放大)相乘,就会得到一个透明的彩色unity logo



二、实践
1、准备场景资源
首先我们分别新建一个表面着色器和材质,都命名为Mask,将shader赋予材质。
然后编辑shader代码,把无关的属性和代码都删掉,精简代码如下,只留一个主贴图属性:
Shader "Custom/Mask" {
Properties {
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Standard
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
我们在场景里新建一个Plane,赋上Mask材质,材质的Albedo贴图槽选择color贴图,现在材质的效果应该是这样的:

2、增改shader代码
Shader "Custom/Mask" {
Properties {
_MainTex("Albedo (RGB)", 2D) = "white" {}
_MaskTex("Mask", 2D) = "white" {} //add
}
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Transparent"} //modified
Blend SrcAlpha OneMinusSrcAlpha //add
CGPROGRAM
#pragma surface surf Standard keepalpha //modified
#pragma target 3.0
sampler2D _MainTex;
sampler2D _MaskTex; //add
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
fixed4 m = tex2D (_MaskTex, IN.uv_MainTex); //add
c = c * m; //add
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
这三句修改的代码都是为了让shader支持透明
Tags { "RenderType"="Opaque" "Queue"="Transparent"} //modified
Blend SrcAlpha OneMinusSrcAlpha //add
#pragma surface surf Standard keepalpha //modified
最后我们把mask贴图拖进材质新增的Mask贴图槽

现在材质效果应该就是这样了:

三、优化
但是通常我们用的mask贴图都不是透明贴图,而是黑白贴图。这是因为带透明通道的贴图消耗更高,而只要我们稍微改一下代码,黑白mask贴图可以实现和透明mask贴图完全一样的效果。
我们再将shader代码修改如下,仅需改一处代码:
Shader "Custom/Mask" {
Properties{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_MaskTex("Mask", 2D) = "white" {}
}
SubShader{
Tags { "RenderType" = "Opaque" "Queue" = "Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma surface surf Standard keepalpha
#pragma target 3.0
sampler2D _MainTex;
sampler2D _MaskTex;
struct Input {
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutputStandard o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
fixed4 m = tex2D(_MaskTex, IN.uv_MainTex);
c = c * m.r; //modified
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

然后我们再把透明mask贴图换成黑白的mask贴图,可以得到同样的遮罩效果。
网友评论