The following is from the introduction to unity shader
Calculate light in tangent space:
The light direction and the viewing angle direction are all converted to tangent space for calculation.
To calculate light in world space:
The normal direction obtained from the normal texture is converted to the world space, and then calculated with the light direction and perspective direction in the world space.
Method 1:
Tangent space rotation is a macro, refer to: https://blog.csdn.net/ronintao/article/details/52136673
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Unity Sader Book/Chapter7/Chapter7-NormalMapTangentSpace" { Properties { _Color( "Color Tint", Color ) = ( 1,1,1,1 )//Overall tone _MainTex ("Texture", 2D) = "white" {} _BumpMap( "Normal Map", 2D ) = "bump" { }//normal map _BumpScale( "Bump Scale", Float ) = 1.0 _Specular( "Specular", Color ) = (1,1,1,1)//Mirror light _Gloss( "Gloss", Range( 8.0, 256 ) ) = 20//bright } SubShader { Pass { Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" #include "Lighting.cginc" float4 _Color; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _BumpMap; float4 _BumpMap_ST; float _BumpScale; float4 _Specular; float _Gloss; struct a2v { float4 vertex : POSITION; float3 normal : Normal; float4 tangent : TANGENT;//tangent float4 texcoord : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float4 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; o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw; //float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) )*v.tangent.w; //float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal ); 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 ); //Get the texture in the normal map fixed4 packedNormal = tex2D( _BumpMap, i.uv.zw ); fixed3 tangentNormal; //If the texture type is not set to Normal Map, you need to manually reflect packedNormal as the normal direction //tangentNormal.xy = (packedNormal.xy*2 - 1)*_BumpScale, _BumpScale //tangentNormal.z = sqrt( 1.0 - saturate( dot( tangentNormal.xy, tangentNormal.xy ) ) ) //If the texture type has been set to Normal Map, use the built-in function to get the correct normal direction tangentNormal = UnpackNormal( packedNormal ); 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; fixed3 diffuse = _LightColor0.rgb * albedo * max( 0, dot( tangentNormal, tangentLightDir ) ); fixed3 halfDir = normalize( tangentLightDir + tangentViewDir ); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow( max(0, dot(tangentNormal, halfDir )), _Gloss ); return fixed4( ambient + diffuse + specular, 1.0 ); } ENDCG } } Fallback "Specular" }