以下内容来自《unity shader入门精要》
切线空间下计算光照:
光照方向,视角方向全部转换到切线空间下计算。
世界空间下 计算光照:
将从法线纹理上得到的法线方向转换到世界空间下,之后再和世界空间下的光照方向,视角方向进行计算。
方法一:
TANGENT_SPACE_ROTATION是一个宏,参考:https://blog.youkuaiyun.com/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 )//整体的色调
_MainTex ("Texture", 2D) = "white" {}
_BumpMap( "Normal Map", 2D ) = "bump" { }//法线纹理
_BumpScale( "Bump Scale", Float ) = 1.0
_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
// 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;//切线
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 texel in the normal map在法线贴图中获取纹理
fixed4 packedNormal = tex2D( _BumpMap, i.uv.zw );
fixed3 tangentNormal;
//如果texture类型没有设置成Normal Map,需要手动将packedNormal反映射为法线方向
//tangentNormal.xy = (packedNormal.xy*2 - 1)*_BumpScale, _BumpScale
//tangentNormal.z = sqrt( 1.0 - saturate( dot( tangentNormal.xy, tangentNormal.xy ) ) )
//如果已经将texture类型设置成了Normal Map, 那么使用内置函数获取正确的法线方向
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"
}