遮罩纹理
遮罩允许我们保护某些区域,使他们免于某些修改。为了得到更加细腻的效果,我们使用遮罩,使得某些地方反光强烈一些,某些地方弱一些。
使用遮罩纹理的一般流程是:通过采样得到遮罩纹理的纹素值,然后使用其中某个或某几个通道的值来与某种表面属性相乘,这样,当该通道的值为0时,可以保护该表面不受该属性的影响。
实践:
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 tangentLightDir = normalize(i.lightDir);
fixed3 tangentViewDir = normalize(i.viewDir);
fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uv));
tangentNormal.xy *= _BumpScale;
tangentNormal.z = sqrt(1 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss) * specularMask;
return fixed4(ambient + diffuse + specular, 1);
}
我们为主纹理_MainTex、法线纹理_BumpMap、遮罩纹理_SpecularMask定义了共同使用的纹理属性变量_MainTex_ST,这样可以节省需要存储的纹理坐标数。
在计算高光反射时,我们先对遮罩纹理_SpecularMask进行采样,然后选择使用了r分量来计算掩码值,然后与_SpecularScale相乘,一起来控制高光反射的强度。
效果图: