遮罩纹理其实内容不是很多,说白了就是添加一张纹理来存储权重值,以控制渲染中某些变量的值。由于一张图中有四个通道(r,g,b,a),因此一张图可以控制四个变量。
下面主要讲一下通过一张纹理来控制高光的效果。
图一 未添加遮罩贴图效果
图二 添加遮罩贴图效果
从图一图二中对比可以看出,图二添加了遮罩贴图后高光部分显得比较暗淡。
在shader中:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/3.4.1" {//渐变纹理
Properties{
_Color("Color Tint", Color) = (1, 1, 1, 1)
_MainTex("Main Tex",2D) = "white"{}
_BumpTex("Bump Tex",2D) = "white"{}
_BumpScale("Bump Scale",Float) = 1.0
_MaskTex("Mask Tex",2D) = "white"{}
_MaskScale("Mask Scale",Float) = 1.0
_Specular("Specular", Color) = (1, 1, 1, 1)
_Gloss("Gloss", Range(8.0, 256)) = 20
}
SubShader{
Pass{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;//一张贴图就应该对应一个_ST变量,可以共用一个缩放变量
sampler2D _BumpTex;
sampler2D _MaskTex;
float _BumpScale;
float _MaskScale;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv:TEXCOORD0;
float3 lightDir:TEXCOORD1;
float3 viewDir:TEXCOORD2;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//将模型空间转到剪切空间
o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//缩放后再位移
//为之后计算凹凸纹理做准备先将光线和视线方向转到切线空间
TANGENT_SPACE_ROTATION;
o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
o.viewDir = mul(rotation,ObjSpaceViewDir(v.vertex)).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed3 lightDir = normalize(i.lightDir);
fixed3 viewDir = normalize(i.viewDir);
fixed3 albedo = tex2D(_MainTex, i.uv).rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;//环境光
//然后计算凹凸纹理
fixed3 bump = UnpackNormal(tex2D(_BumpTex, i.uv));//获取凹凸纹理贴图的内容
bump.xy *= _BumpScale;
bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
fixed3 diffuse = _LightColor0.rgb * ambient * max(0, dot(bump, lightDir));//漫反射
fixed3 halfDir = normalize(lightDir + viewDir);
fixed3 maskTex = tex2D(_MaskTex, i.uv) * _MaskScale;
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss) * maskTex;
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
漫反射和高光部分其实使用的方法都比较传统,漫反射使用传统的光照颜色*漫反射颜色*max(0,发现和光照角度)。
这里使用的遮罩纹理由于rgb通道都为同一个值,因此实现效果只有降低高光的强度。
fixed3 maskTex = tex2D(_MaskTex, i.uv) * _MaskScale;
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss) * maskTex;
第一行代码来获取遮罩纹理的四个通道,第二行代码直接将值与高光计算结果相乘。因为计算的高光结果乘了一个小于1的值,因此三个通道都相对减少,因此整体高光部分强度降低。
这里要说一下的事,其实我们之前在做虚拟试衣的时候使用的透明贴图也属于一种遮罩纹理。但是只是用了a通道的值。