1. 程式人生 > >Unity Shader 法線貼圖的實現

Unity Shader 法線貼圖的實現

計算 變換 float minus include 的確 dal 反射 mode

這裏有一個細節,關於法線貼圖是有兩個不同的空間的,如下:

  切線空間:法線貼圖顏色為偏藍色

  模型空間:法線貼圖顏色為五顏六色

因此根據不同的空間變換位置方便一致計算。

  1 // 法線貼圖映射的編寫+透明
  2 Shader "TMoon/05-NormalMapAndAlpha" {
  3     Properties{
  4         _Color("Color",Color) = (1,1,1,1)
  5         _MainTex("Main Tex",2D) = "white"{}
  6         _NormalMap("Normal Map",2D) = "
bump"{} //bump默認值的意思:若沒有法線貼圖,則使用頂點自帶的 7 _BumpScale("Bump Scale",Float) = 1 8 _AlphaScale("Alpha Scale",Float) = 1 9 } 10 11 SubShader{ 12 13 Tags{ "Queue" = "Transparent" "IngnoreProjector" = "True" "RenderType" = "Transparent" } 14 15 Pass{
16 17 Tags {"LightMode" = "ForwardBase"} 18 19 ZWrite Off 20 Blend SrcAlpha OneMinusSrcAlpha 21 22 CGPROGRAM 23 24 #include "Lighting.cginc" 25 26 #pragma vertex vert 27 #pragma fragment frag 28
29 fixed4 _Color; 30 sampler2D _MainTex; 31 float4 _MainTex_ST; 32 sampler2D _NormalMap; 33 float4 _NormalMap_ST; 34 float _BumpScale; 35 float _AlphaScale; 36 37 // application to vertex 38 // 由應用程序傳遞給頂點函數 39 struct a2v { 40 float4 vertex:POSITION; 41 float3 normal:NORMAL; // 切線空間的確定是通過(存儲模型裏的)法線和(存儲模型裏的)切線確定的,所以需要模型的法線 42 float4 texcoord:TEXCOORD0; // 模型的紋理坐標 43 float4 tangent:TANGENT;// 模型空間的切線 44 }; 45 46 // vertex to fragment 47 // 由頂點函數傳遞給片元函數 48 struct v2f { 49 float4 svPos:SV_POSITION; 50 float4 uv:TEXCOORD0; // uv.xy 存儲MainTex的紋理坐標,uv.zw 存儲法線貼圖的紋理坐標 51 float3 lightDir : TEXCOORD1; // 切線空間下平行光的方向 52 }; 53 54 v2f vert(a2v v) { 55 v2f f; 56 57 f.svPos = mul(UNITY_MATRIX_MVP, v.vertex); 58 59 // 將MainTex紋理坐標賦值給v2f.uv.xy並賦值面板貼圖的旋轉縮放 60 f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; 61 // 將法線貼圖紋理坐標賦值給v2f.uv.zw並賦值面板貼圖的旋轉縮放 62 f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw; 63 64 // 調用這個宏之後,會得到一個矩陣 rotation 65 // 這個矩陣用來把模型空間下的方向轉換成切線空間下 66 TANGENT_SPACE_ROTATION; 67 68 //ObjSpaceLightDir(v.vertex) 得到模型空間下的平行光方向 69 f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); 70 71 return f; 72 } 73 74 float4 frag(v2f f) : SV_Target{ 75 76 // tex2D 根據法線貼圖的紋理坐標獲取顏色值 77 fixed4 normalColor = tex2D(_NormalMap,f.uv.zw); 78 79 // 切線空間下的法線 80 fixed3 tangentNormal = UnpackNormal(normalColor); 81 tangentNormal.xy = tangentNormal.xy * _BumpScale; 82 tangentNormal = normalize(tangentNormal); 83 84 fixed3 lightDir = normalize(f.lightDir); 85 86 // tex2D 根據MainTex貼圖的紋理坐標獲取顏色值 87 fixed3 texColor = tex2D(_MainTex,f.uv.xy) * _Color.rgb; 88 89 // 為漫反射混合上每個像素點的紋理顏色 90 fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0); 91 92 return fixed4(diffuse, _AlphaScale); 93 } 94 95 ENDCG 96 } 97 } 98 99 Fallback "VertexLit" 100 }

Unity Shader 法線貼圖的實現