Unity Shader 法線貼圖的實現


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

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

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

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

  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM