1. 程式人生 > >Unity3D Shader 入門之簡單案例的實現(通過法線實現顏色變化)

Unity3D Shader 入門之簡單案例的實現(通過法線實現顏色變化)

在沒有接觸Unity3D  Shader 之前,總感覺shader特別神奇,因為聽說是對渲染流水線進行程式設計,就是對GPU進行程式設計。聽著特別高大上。這不,最近剛剛接觸Shader,學了幾個小案例,然後本文作為學習筆記將這個小案例的實現記錄下來。

筆者也是剛開始學習shader 沒幾天。在剛開始學shader 的時候,剛覺shader好難,面對shader一些奇怪的語法和一些語義,有點讓人頭疼。學著感覺一頭霧水,因為在學一些小案例之前還需要學習(複習)一些數學知識,因為涉及到座標空間的轉換,所以看了很多矩陣運算和其他的一些數學知識。

我想很多學shader的人和我一樣吧,剛開始接觸shader的時候,發覺好難,我覺是因為沒有實現過一些小案例,所以讓shader披上了一層神祕的面紗。等實現了一些小案例就會發現,原來這東東是這樣玩的···

接下來我們就來實現一個小案例,效果如下圖:

 

然後來看看實現這種效果的過程

1.首先我們先建立一個測試專案,然後建立一個material(材質) 和 shader  ,在場景中建立一個球體和膠囊體。

2.把建立的shader賦給材質:

3.接下來就開啟編輯器對shader進行編輯。

在此之前我們先來簡單瞭解以下shader框架

Shader "Custom/myshader"{
    Properties
    {
              // 屬性
    }
    Subshader
    {
              // 用於實現效果
    }
}
        

簡單瞭解過後,我們在Properties區域新增我們所需要的屬性

    Properties
    {
        _Color("Base Color",color)=(1,1,1,1)
        _MainTex("Base(RGB)",2D) = "white"{}
    }

屬性將會顯示在材質的屬性面板上,我們就可以通過面板對上面兩個屬性進行值的變換。為了讓美術和程式設計師合作,在shader中屬性的定義就是作為一個介面,程式設計師定義這個介面讓美術來調節渲染效果。

然後來看shader的核心部分,Subshader

Subshader
    {
     Tags{"Queue" = "transparent"  "RenderType" = "transparent"  "IgoreProjector" = "true" }     // 定義渲染所需要的一些標籤,讀者可以去查閱其他資料進行了解,在此不再累述
     Blend  SrcAlpha  oneMinusSrcAlpha     // 混合
     pass          // 渲染通道   注:一個Subshader裡可以有多個pass
     {
        CGPROGRAM                 // 開始CG程式碼
        #pragma vertex vert       // 重點,對頂點vert函式進行宣告 
        #pragma fragment frag     // 對片元frag函式進行宣告
        #include "UnityCG.cginc"  // 引入需要的檔案(就像C++語言裡的include一樣)

        sampler2D _MainTex;  // 變數名稱要和properties中的變數名稱相同,這個變數就有值了。
        float4 _Color;       // 同上

        struct v2f        // 結構體的定義是為了 vert  到   frag  的過度
        {
            float4 pos : POSITION;
            float4 uv   : TEXCOORD;
            float4 col :COLOR;
        };
        v2f vert(appdata_base v)    // appdata_base 來自於UnityCG.cginc    
        {
            v2f  o;
            o.pos = UnityObjectToClipPos(v.vertex);   // 座標空間的轉換
            o.uv = v.texcoord;
            o.col.xyz = v.normal*0.5+0.5;   // 法線的取值範圍是-1到1   所以先乘0.5讓範圍到-0.5到0.5  ,在加上0.5,就符合顏色的取值範圍了。
            o.col.w = 1.0;
            return o;
        }
        half4 frag(v2f i) :COLOR 
        {
            half4 h = i.col;     // 賦值顏色
            return h;
        }
        ENDCG         // 結束CG程式碼
     }

寫的很簡要,不過對於對shader有一小點了解的讀者來說可以理解了。

以下是完整原始碼:

Shader "Custom/myshader"{
    Properties
    {
        _Color("Base Color",color)=(1,1,1,1)
        _MainTex("Base(RGB)",2D) = "white"{}
    }
    Subshader
    {
     Tags{"Queue" = "transparent"  "RenderType" = "transparent"  "IgoreProjector" = "true" }
     Blend  SrcAlpha  oneMinusSrcAlpha     
     pass 
     {
        Cull off
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

        sampler2D _MainTex;
        float4 _Color;

        struct v2f
        {
            float4 pos : POSITION;
            float4 uv   : TEXCOORD;
            float4 col :COLOR;
        };
        v2f vert(appdata_base v)
        {
            v2f  o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.uv = v.texcoord;
            o.col.xyz = v.normal*0.5+0.5;   
            o.col.w = 1.0;
            return o;
        }
        half4 frag(v2f i) :COLOR 
        {
            half4 h = i.col;
            return h;
        }
        ENDCG
     }
    }
}

&n