法線貼圖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
}
}
}