【UnityShader】渐变纹理


一开始普遍认为渲染中使用纹理是来定义物体的颜色,但后来纹理其实可以存储任何表面属性。

其中就有下文介绍的用渐变纹理来控制漫反射光照的结果。

渐变纹理的关键就在于如何把渐变纹理坐标和漫反射光照联系起来。

这里使用了半兰伯特模型,通过半兰伯特部分的纹理坐标去采样渐变纹理。这样在材质颜色和采样取得的颜色相乘就形成了最终的漫反射光照。

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Chapter7-RampTexture"
{
   Properties{
    _Color("Color Tint",Color) = (1,1,1,1)
    _RampTex("Ramp Tex",2D) = "white"{}  //渐变纹理
    _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 _RampTex; 
        float4 _RampTex_ST;
        float _Gloss;
        fixed4 _Specular;

        struct a2v{
            float4 vertex:POSITION;
            float3 normal:NORMAL;
            float4 texcoord:TEXCOORD; 
        };

        struct v2f{
            float4 pos:SV_POSITION;
            float3 worldNormal:TEXCOORD0;
            float3 worldPos:TEXCOORD1;
            float2 uv:TEXCOORD2;
        };

        v2f vert(a2v v)
        {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.worldNormal = UnityObjectToWorldNormal(v.normal);
            o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
            //o.uv = v.texcoord.xy*_RampTex_ST.xy+_RampTex_ST.zw;
            
            o.uv = TRANSFORM_TEX(v.texcoord,_RampTex);

            return o;
        }

        fixed4 frag(v2f i):SV_Target{
            fixed3 worldNormal = normalize(i.worldNormal);
            fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

            fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
            
            fixed halfLambert = 0.5*dot(worldNormal,worldLightDir)+0.5;           
            fixed3 diffuseColor = tex2D(_RampTex,fixed2(halfLambert,halfLambert)).rgb*_Color.rgb;  //用半兰伯特采样,色调和漫反射就挂钩了 渐变纹理只与u方向有关,所以v值可任意
            fixed3 diffuse = _LightColor0*diffuseColor;

            //fixed3 albedo =tex2D(_RampTex,i.uv).rgb*_Color.rgb;    //对比采样自身纹理坐标,无法与漫反射联系
            //fixed3 diffuse = _LightColor0.rgb*max(0,dot(worldNormal,worldLightDir))*albedo;

            fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
            fixed3 halfDir = normalize(worldLightDir+viewDir);
            fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(max(0,dot(worldNormal,halfDir)),_Gloss);

            return fixed4(ambient+diffuse+specular,1.0);
        }
        
        ENDCG
        }
        }
    FallBack "Specular"
}