天天看點

【Unity】ShaderLab-3_2-法線貼圖

法線貼圖ShaderLab實作

  • 切線空間下計算的法線貼圖
  • 世界空間下計算的法線貼圖
/**********
*
* 作者   :   Quaye
* 時間   :   2018.06.04
*
* 描述   :     切線空間下計算的法線貼圖
*
**/
Shader "Quaye/_NormalMapTangentSpace" 
{
    Properties
    {
        _MainColor("TextureColor",Color)=(,,,)
        _MianTexture("MainTexture",D) = "white"{}
        _BumpScale("BumpScale" ,float) = 
        _BumpTexture("BumpTexture",D) = "bump"{}

        _Specular("Specular",Color)=(,,,)
        _Gloss("Gloss",Range(,)) = 
    }
    SubShader
    {
        Pass
        {
            Tags{ "LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex   vert
            #pragma fragment frag
            #include "Lighting.cginc"

            sampler2D   _MianTexture;
            float4      _MianTexture_ST;

            sampler2D   _BumpTexture;
            float4      _BumpTexture_ST;

            fixed4 _MainColor;          
            fixed4 _Specular;
            float _BumpScale;
            float _Gloss;

            struct a2v
            {
                float4 pos      :   POSITION;
                float3 normal   :   NORMAL;
                float4 tangent  :   TANGENT;
                float4 texcoord :   TEXCOORD0;
            } ;
            struct v2f
            {
                float4 pos      :   SV_POSITION;
                float4 uv       :   TEXCOORD0;
                float3 tVDir    :   TEXCOORD1;
                float3 tLDir    :   TEXCOORD2;
            };


            v2f vert (a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.pos);
                o.uv.xy = v.texcoord.xy * _MianTexture_ST.xy + _MianTexture_ST.zw ;
                o.uv.zw = v.texcoord.xy * _BumpTexture_ST.xy + _BumpTexture_ST.zw ;

                // 計算rotation:法線 X 切線 = 副切線(兩個方向),計算後再 * 切線的 w 分量确認方向
                // 這兩行代碼等價于内置函數:TANGENT_SPACE_ROTATION
                float3 binormal  = cross(normalize(v.normal),normalize(v.tangent.xyz))*v.tangent.w;
                float3x3 rotation = fixed3x3(v.tangent.xyz, binormal, v.normal);
                // TANGENT_SPACE_ROTATION ;  

                o.tVDir = mul(rotation , ObjSpaceViewDir (v.pos)).xyz  ;
                o.tLDir = mul(rotation , ObjSpaceLightDir(v.pos)).xyz  ;

                return o;
            }

            fixed4 frag (v2f f):SV_TARGET
            {
                fixed3 tV = normalize(f.tVDir);
                fixed3 tL = normalize(f.tLDir);

                // 法線貼圖紋理采樣
                fixed3 normalMap = tex2D(_BumpTexture,f.uv.zw );

                fixed3 tN;
                // 法線texel映射回法線方向。乘減大法:法線分量為[-,],而像素分量為[,]
                tN.xy = (normalMap.xy *-)*_BumpScale;
                // 發線是機關向量,是以 z 分量需要
                tN.z = sqrt(- saturate(dot(tN.xy,tN.xy)));

                fixed3 albedo = tex2D(_MianTexture,f.uv.xy) * _MainColor.rgb;

                fixed3 ambient  = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse  = _LightColor0.rgb * albedo * saturate(dot(tL,tN));

                fixed3 h        = normalize(tL + tV); 
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tN,h)),_Gloss);

                return fixed4(ambient + diffuse + specular, );
            }

            ENDCG
        }
    }
}

           
/**********
*
* 作者   :   Quaye
* 時間   :   2018.06.06
*
* 描述   :     世界空間下計算的法線貼圖
*
**/
Shader "Quaye/_NormalMapWorldSpace" 
{
    Properties
    {
        _Color("Color",Color)           = (,,,)
        _MainTex("Main Tex",D)         = "white"{}
        _BumpScale("Bump Scale",float)  = 
        _BumpMap("Normal Map",D)       = "bump"{}
        _Specular("Specular",Color)     = (,,,)
        _Gloss("Gloss",Range(,))    = 
    }

    SubShader
    {
        pass
        {
            Tags{"LightMode" = "ForwardBase"}

            CGPROGRAM
            #pragma vertex      vert 
            #pragma fragment    frag 

            #include "Lighting.cginc"

            fixed4      _Color;
            sampler2D   _MainTex;
            float4      _MainTex_ST;

            float       _BumpScale;
            sampler2D   _BumpMap;
            float4      _BumpMap_ST;

            fixed4      _Specular;
            float       _Gloss;

            struct a2v 
            {
                float4 vertex   : POSITION;
                float3 normal   : NORMAL;
                float4 tangent  : TANGENT;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f 
            {
                float4 pos      : SV_POSITION;
                float4 uv       : TEXCOORD;
                float4 TtoW0    : TEXCOORD1;
                float4 TtoW1    : TEXCOORD2;
                float4 TtoW2    : TEXCOORD3;
            };

            v2f vert (a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

                // 計算世界空間下的頂點、頂點切線、副切線、法線的矢量表示
                float3 worldPos     = mul(unity_ObjectToWorld,v.vertex).xyz;
                float3 worldNormal  = UnityObjectToWorldNormal(v.normal);
                float3 worldTangent = UnityObjectToWorldDir(v.tangent);
                float3 worldBinormal= cross(worldNormal,worldTangent) * v.tangent.w;
                // 按列排列,得到從切線空間到世界空間的變換矩陣
                o.TtoW0 = float4(worldTangent.x,worldBinormal.x,worldNormal.x,worldPos.x);
                o.TtoW1 = float4(worldTangent.y,worldBinormal.y,worldNormal.y,worldPos.y);
                o.TtoW2 = float4(worldTangent.z,worldBinormal.z,worldNormal.z,worldPos.z);

                return o;
            };

            fixed4 frag (v2f i):SV_TARGET
            {
                float3 wP = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
                fixed3 wL = normalize(UnityWorldSpaceLightDir(wP));
                fixed3 wV = normalize(UnityWorldSpaceViewDir(wP));

                fixed4 packedNormal = tex2D(_BumpMap,i.uv.zw);
                fixed3 tN ;
                // 法線texel映射回法線方向。乘減大法:法線分量為[-,],而像素分量為[,]
                tN.xy = (packedNormal.xy * - ) *_BumpScale;
                tN.z = sqrt( - saturate( dot (tN.xy ,tN.xy )));

                fixed3 wN = normalize( half3( dot(i.TtoW0.xyz, tN),
                                              dot(i.TtoW1.xyz, tN),
                                              dot(i.TtoW2.xyz, tN))
                                    );

                fixed3 albedo = tex2D(_MainTex,i.uv.xy) * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(wL,wN));

                fixed3 h = normalize(wL+wV);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(wN,h)),_Gloss);

                return fixed4(ambient + diffuse + specular,);
            }
            ENDCG

        }
    }

}