unity shader 学习 MaskTexture

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unity Shader Book/Chapter 7/MaskTexture"
{
    Properties
    {
        _Color("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex("Main Tex", 2D) = "white" {}
        _BumpMap("Normal Map", 2D) = "bump" {}
        _BumpScale("Bump Scale", Float) = 1.0
        _SpecularMask("Specular Mask", 2D) = "white" {}
        _SpecularScale("Specular Scale", Float) = 1.0
        _ShadowMask("Shadow Mask", 2D) = "white" {}
        _ShadowScale("Shadow Scale", Float) = 1.0
        _Specular("Specular", Color) = (1, 1, 1, 1)
        _Gloss("Gloss", Range(8.0, 256)) = 20
    }
        SubShader
        {
                Tags{"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
                // No culling or depth
                Pass
                {
                    Tags{ "LightMode" = "ForwardBase" }

                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag

                    #include "UnityCG.cginc"
                    #include "Lighting.cginc"

                    struct a2v
                    {
                        float4 vertex : POSITION;
                        float3 normal : NORMAL;
                        float4 tangent : TANGENT; //顶点切线方向  tangent.w 分量来决定切线空间中的第三个坐标轴(福切线的方向性)
                        float4 texcoord : TEXCOORD0;  //纹理坐标
                    };

                    struct v2f
                    {
                        float4 pos : SV_POSITION;
                        float2 uv : TEXCOORD0;
                        float3 lightDir : TEXCOORD1;
                        float3 viewDir : TEXCOORD2;
                    };

                    fixed4 _Color;
                    sampler2D _MainTex;
                    float4 _MainTex_ST;
                    sampler2D _BumpMap;
                    float _BumpScale;
                    sampler2D _SpecularMask;
                    float _SpecularScale;
                    sampler2D _ShadowMask;
                    float _ShadowScale;
                    fixed4 _Specular;
                    float _Gloss;

                    v2f vert(a2v v)
                    {
                        v2f o;
                        o.pos = UnityObjectToClipPos(v.vertex);  //模型裁剪空间的坐标
                        //主贴图uv坐标 = 自身缩放 * 主贴图缩放 + 主贴图偏移值
                        o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                        //构造出  tangent  space 的坐标系, 定义转换world space的向量到tangent space的rotation 矩阵。
                        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.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));

                        //自身颜色 = 贴图颜色 + 设置颜色
                        fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
                        //自身颜色 = 系统灯光颜色(天空盒子) + 设置颜色
                        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                        //漫反射 = 灯光颜色 * 自身颜色 * 法线方向到灯光方向的角度(0是背面 1是正面)
                        fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
                        //灯光到视角的反方向
                        fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
                        //遮罩 = 覆盖纹理 遮码值(r) * 缩放大小
                        fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
                        fixed shadowMask = tex2D(_ShadowMask, i.uv).r * _ShadowScale;
                        //反射 = 灯光颜色 * 设置颜色 * pow(反射角度(取值范围0~1), 程度) * 遮罩 * 遮罩  双层遮罩
                        fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(tangentNormal,halfDir)),_Gloss) * specularMask * shadowMask;
                        //灯光颜色 + 自身颜色 + 高光颜色
                        return fixed4(ambient + diffuse + specular,1.0);
                    }
                    ENDCG
                }
        }
            Fallback "Specular"
}
 

Unity Shader 中的 Texture Mask 意思是使用一张灰度图作为遮罩来控制另一张纹理的显示程度。这种技术通常用于实现一些特效效果,例如角色的阴影、光照效果等等。 下面是一个简单的 Texture Mask Shader 的实现: ```c# Shader "Custom/TextureMask" { Properties { _MainTex ("Texture", 2D) = "white" {} _MaskTex ("Mask Texture", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" } LOD 100 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; sampler2D _MaskTex; fixed4 _Color; struct Input { float2 uv_MainTex; float2 uv_MaskTex; }; void surf (Input IN, inout SurfaceOutput o) { // 取样原始纹理和 Mask 纹理 fixed4 c = tex2D(_MainTex, IN.uv_MainTex); float mask = tex2D(_MaskTex, IN.uv_MaskTex).r; // 根据 Mask 灰度值来控制显示程度 o.Albedo = c.rgb * mask; o.Alpha = c.a * mask; o.Emission = 0; } ENDCG } FallBack "Diffuse" } ``` 在这个 Shader 中,我们定义了两个属性 `_MainTex` 和 `_MaskTex` 分别表示原始纹理和 Mask 纹理。然后在 `surf` 函数中,我们通过 `tex2D` 函数取样两个纹理,并根据 Mask 灰度值来控制原始纹理的显示程度。 在使用这个 Shader 的时候,只需要将原始纹理和 Mask 纹理分别赋值给 `_MainTex` 和 `_MaskTex` 属性即可: ```c# Material mat = new Material(Shader.Find("Custom/TextureMask")); mat.SetTexture("_MainTex", originalTexture); mat.SetTexture("_MaskTex", maskTexture); ``` 这样就可以使用 Mask 纹理来控制原始纹理的显示程度了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值