Unity Shader入門教程(一)

Unity Shader是着色器,將紋理、網格信息輸入,得到材質的一段程序,具體是個什麼東西,還需要親自實踐才知道。一個Unity大神推薦我:如果要學計算機圖形編程(遊戲編程的基礎),可以先學習UnityShader,往後再學習OpenGLDX。不說廢話,依我的風格,都是直接看實例,筆者的教程偏向於傻瓜式的,應該適合入門。

 

前提:安裝了UnityVS,並且有3天的Unity使用經驗。

 

第一步:打開新工程。在內容瀏覽器中創建一個Shader

命名爲:

第二步:雙擊打開查看:

複製代碼
Shader "Custom/Shad0" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
複製代碼

當然,你一開始看不懂,請逐行逐行看我的解釋,下文中的代碼和上文中的一樣,只是加入了詳細的註釋:

複製代碼
/*首行聲明瞭一個Shader,命名爲Shad0,存放在路徑Custom下(這個路徑在哪裏不是重點,它歸類在自定義中),看上去是不是挺像結構體的聲明*/
Shader "Custom/Shad0" {

    /*
    在將第一塊內容之前,請先去了解一下UV紋理。簡單來說:A是一張圖片(稱A爲紋理),B是一張座標信息(稱B爲UV),用B來取A就是紋理貼圖的精髓了,舉個簡單的例子:
    A的色彩如下:
    紅 黃
    藍 綠

    B的座標信息如下:
    (0,0) (1,1)
    (1,1) (0,1)

    那麼取出來得到的紋理貼圖就是:
    紅 綠
    綠 黃

    這樣子,是不是很無聊?當這上面的點數達到很大的量級時,就很有意義了。
    沒完,你還需要了解鏡面高光和金屬度的概念,自行百度(或者先跳過這個知識點繼續往下看)。
    */

    /*第一塊:屬性聲明*/
    Properties {

        _Color ("Color", Color) = (1,1,1,1)
        /*用_XX的聲明方法來聲明的變量就是稱爲屬性了,這一句的語法是:
        _XXX (展示名, 數據類型) = 默認值

        展示名是在Unity中可見的名稱,Color其實是一種數據類型(就像int那樣,只是後者很簡單,是基本數據類型)。
        數據類型有哪些(參考上述博文):
        Color - 一種顏色,由RGBA(紅綠藍和透明度)四個量來定義;
        2D - 一張2的階數大小(256,512之類)的貼圖。這張貼圖將在採樣後被轉爲對應基於模型UV的每個像素的顏色,最終被顯示出來;
        Rect - 一個非2階數大小的貼圖;
        Cube - 即Cube map texture(立方體紋理),簡單說就是6張有聯繫的2D貼圖的組合,主要用來做反射效果(比如天空盒和動態反射),也會被轉換爲對應點的採樣;
        Range(min, max) - 一個介於最小值和最大值之間的浮點數,一般用來當作調整Shader某些特性的參數(比如透明度渲染的截止值可以是從0至1的值等);
        Float - 任意一個浮點數;
        Vector - 一個四維數;

        請看默認值(1,1,1,1),形如(g,b,a,A),其中的透明度A爲0時,表示透明,爲1時,表示完全不透明,所以應該稱之爲不透明度。
        */
        
        
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        /*這裏表示一張圖片,這張圖片在這裏僅僅用空白來表示*/
    
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        /*高光設置爲.5*/

        _Metallic ("Metallic", Range(0,1)) = 0.0
        /*金屬度*/
    }


    /*第二塊內容:什麼是SubShader,如果你用過虛幻4,就能夠很容易理解,其實SubShader對應了UE4中的材質表達式。
    UE4中的材質表達式或者Unity中的shader本質是什麼?簡單來說就是將圖片通過處理得到另一張圖片(比如用圖片+UV信息 -> 紋理貼圖的過程)。
    SubShader其實就是定義了圖片處理過程。
    */
    SubShader {
        
        /*Tags規定了混合模型。什麼是混合模型?請看下面的附圖1,當然,混合模型是UE4中的概念。
複製代碼

附圖1

複製代碼
        這裏貼一段相比Unity更爲正確的解釋:
        Background - 最早被調用的渲染,用來渲染天空盒或者背景
        Geometry - 這是默認值,用來渲染非透明物體(普通情況下,場景中的絕大多數物體應該是非透明的)
        AlphaTest - 用來渲染經過Alpha Test的像素,單獨爲AlphaTest設定一個Queue是出於對效率的考慮
        Transparent - 以從後往前的順序渲染透明物體
        Overlay - 用來渲染疊加的效果,是渲染的最後階段(比如鏡頭光暈等特效)

        */
        Tags { "RenderType"="Opaque" }


        /*LOD表示細節呈現級別(也即是畫質,即粗糙/細膩程度)
        當機器很差的時候,差到其評估值小於200時,本材質無效(也就是本shader罷工)。當機器的性能不錯,大於200時,本shader繼續工作。就是這麼有個性。
        彆氣餒,下面的內容是最重要的。
        */
        LOD 200
        

        /*這是一個標記:CGPROGRAM,表示這是一段computer graph編程*/
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
            /*請看這個奇怪的函數聲明:
            #pragma surface表面着色器 surffunction着色器的代碼(在本例子中就是下面的surf) lightModel(光照模型,這個概念先跳過) [可選參數]
            */


        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0


            /*
            用筆者的話來說:sampler2D就是一張圖片……(還記得嗎,就是上文說的A圖片)

            貼一段介紹:
            
            接下來一句sampler2D _MainTex;,sampler2D是個啥?
            其實在CG中,sampler2D就是和texture所綁定的一個數據容器接口。
            等等..這個說法還是太複雜了,簡單理解的話,所謂加載以後的texture(貼圖)說白了不過是一塊內存存儲的,
            使用了RGB(也許還有A)通道,且每個通道8bits的數據。而具體地想知道像素與座標的對應關係,以及獲取這些數據,
            我們總不能一次一次去自己計算內存地址或者偏移,因此可以通過sampler2D來對貼圖進行操作。
            更簡單地理解,sampler2D就是GLSL中的2D貼圖的類型,相應的,
            還有sampler1D,sampler3D,samplerCube等等格式。

            解釋通了sampler2D是什麼之後,
            還需要解釋下爲什麼在這裏需要一句對_MainTex的聲明,
            之前我們不是已經在Properties裏聲明過它是貼圖了麼。
            答案是我們用來實例的這個shader其實是由兩個相對獨立的塊組成的,
            外層的屬性聲明,回滾等等是Unity可以直接使用和編譯的ShaderLab;
            而現在我們是在CGPROGRAM...ENDCG這樣一個代碼塊中,這是一段CG程序。
            對於這段CG程序,要想訪問在Properties中所定義的變量的話,必須使用和之前變量相同的名字進行聲明!【注意這裏!!!】
            於是其實sampler2D _MainTex;做的事情就是再次聲明並鏈接了_MainTex,
            使得接下來的CG程序能夠使用這個變量。*/
        sampler2D _MainTex;


        /*這是一個非常簡單的結構體,稱爲Input,其中有一個float2數據類型,這是一個二維float矢量,也就是(a,b)這樣的。*/
        struct Input {
            float2 uv_MainTex;
        };

        /*在堅持一下,這裏還有幾個變量:half類型的兩個,fixed4類型的一個,
        half類型表示半精度浮點數,計算性能好但是精度低,和float和double是同類型的浮點數;
        fixed4不詳,但是大意是四維的矢量*/
        
        half _Glossiness;//必須使用和之前變量相同的名字進行聲明!【注意這裏!!!】

        half _Metallic;//必須使用和之前變量相同的名字進行聲明!【注意這裏!!!】
        
        fixed4 _Color;//必須使用和之前變量相同的名字進行聲明!【注意這裏!!!】

        /*核心的處理函數:surf,輸入一張二維浮點信息,也即是上面的uv_MainTex,
        輸出一個o表示材質(inout像c++裏面的按照引入傳入,雖說沒有返回,但是也有信息傳出的效果)*/
        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            /*看這裏:tex2D就是前面說的"利用UV去取圖片獲得紋理貼圖"的做法,然後再乘以_Color,
            
            這裏用到了乘法的顏色算法,自己體會(這個_Color默認值爲1,1,1,1,所以默認下不影響)
            筆者到這裏可以知道:fixed4表示一種四維矢量(用來表示顏色就挺合適的。此外,它是定點型小數而非浮點型小數)
            */


            o.Albedo = c.rgb;
            /* inout SurfaceOutputStandard o
            這個結構有哪些包含的變量呢:
            struct SurfaceOutput {
                half3 Albedo;     //像素的顏色
                half3 Normal;     //像素的法向值
                half3 Emission;   //像素的發散顏色
                half Specular;    //像素的鏡面高光
                half Gloss;       //像素的發光強度
                half Alpha;       //像素的透明度
            };
            */

            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
            /*結束CG編碼*/
    }
    FallBack "Diffuse"
        //這裏還不太明白,先放着。
}
複製代碼

第三步:看完之後再重新看看沒有註釋的代碼,整理十分鐘,然後繼續。

第四步:那篇參考的教程到這裏就完了,我補上結尾:

導入一張圖片:

第五步:創建材質Material

在細節裏面選擇shader

是不是很懵逼,爲什麼要這麼做?還記得嗎,shader的本質是將圖片轉化爲Material的算法。

 

第六步:選擇一張圖片:

 

 

然後在右下方看到效果:(點箭頭處切換預覽樣式)

第七步:隨便新建一些物體,然後放入這個材質:

等等:好像沒有反應?因爲沒有光線,加入直射光即可看到效果:

——原創 小江村兒的文傑 [email protected] 201772122:29:44


更多:http://www.cnblogs.com/JackSamuel/default.html?page=2

發佈了56 篇原創文章 · 獲贊 61 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章