1. 程式人生 > >Unity Shader 在Shader中使用法線貼圖

Unity Shader 在Shader中使用法線貼圖

首先我們在Unity中建立一個小球


然後通過"Create->Shader->Standard Surface Shader"建立一個表面著色器,並修改名字為Diffuse Bump

然後通過"Create->Material"建立一個材質,並修改名字為MaterialDiffuseBump,材質使用的shader指定為我們剛建立的Diffuse Bump

下面是Shader程式碼:

Shader "Custom/Diffuse Bump" {
	 //屬性域
    Properties {
      //主紋理屬性
      _MainTex ("Texture", 2D) = "white" {}
      //法線貼圖紋理屬性
      _BumpMap ("Bumpmap", 2D) = "bump" {}
    }
    //Shader執行域
    SubShader {
      //標明渲染型別是不透明的物體
      Tags { "RenderType" = "Opaque" } 
      //標明CG程式的開始
      CGPROGRAM
      //宣告表面著色器函式
      #pragma surface surf Lambert
      //定義著色器函式輸入的引數Input
      struct Input {
      	//主紋理座標值
        float2 uv_MainTex;
        //法線貼圖座標值
        float2 uv_BumpMap;
      };
      //宣告對主紋理圖片的引用
      sampler2D _MainTex;
      //宣告對法線貼圖的引用
      sampler2D _BumpMap;
      //表面著色器函式
      void surf (Input IN, inout SurfaceOutput o) {
	  //賦值顏色資訊
        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
	  //賦值法線資訊
        o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
      }
      //標明CG程式的結束
      ENDCG
      }
}






首先我們來看看這段程式碼unity的Inspector面板中我們都能看到什麼:


我們看到了有兩張紋理貼圖的介面。

我們來看一下這段程式碼和我們之前的一節Surface Shader中的程式碼不同的部分,相同的部分我們不做重複的講解。

首先在屬性域Properties多了一句程式碼:

_BumpMap ("Bumpmap", 2D) = "bump" {}

屬性名字是_BumpMap ,型別是2D的,也就是表示2D紋理的,預設值是bump,也就是凹凸的。我們可以在unity的Inspector面板中看到這個屬性就是第二張紋理貼圖,也就是我們的法線貼圖。

然後再SubShader中我們定義的結構體Input中多了一個變數uv_BumpMap,這個變數用來儲存法線貼圖中的座標。

struct Input {
        float2 uv_MainTex;
        float2 uv_BumpMap;
      };
然後我們聲明瞭一個對法線貼圖屬性_BumpMap的引用:
sampler2D _BumpMap;

最後我們在表面著色器函式surf中把傳入點的法線資訊賦值給輸出的畫素法線資訊。



我們看到這裡出現了一個我們沒見過了UnpackNormal,它表示:


程式碼分析完了,我們來看一下效果

我們把材質MaterialDiffuseBump賦值給我們建立的小球

我這裡有一張板磚的貼圖,和板磚的法線貼圖


我們先只把板磚貼圖賦值材質Material

DiffuseBump對應的屬性中


我們來看看小球的效果,我們在場景中建立一個Directional light光源


我們把板磚的法線貼圖賦值給材質MaterialDiffuseBump


我們再來看一下小球的效果


雖然凹凸感變強了,但我們法線小球變暗了,這是因為法線貼圖影響到了光照的計算,我們會在下一節中講解怎麼是小球的邊緣亮起來。