【Unity Shaders】使用CgInclude讓你的Shader模組化——建立CgInclude檔案儲存光照模型
阿新 • • 發佈:2019-02-13
這裡是本書所有的插圖。這裡是本書所需的程式碼和資源(當然你也可以從官網下載)。
========================================== 分割線 ==========================================
寫在前面
瞭解內建的CgInclude檔案當然很好,但是如果我們想要建立自己的CgInclude檔案來儲存光照模型和輔助函式又該怎麼辦呢?
好訊息是我們的確可以建立自己的CgInclude檔案,壞訊息是我們需要再瞭解一點程式碼語法。好啦,那就開始吧!
準備工作
好訊息是這次的準備工作終於有點不同了。。。壞訊息是我不能再複製貼上了。。。
- 首先,建立一個新的文字檔案,例如MyCgInclude.txt。
- 然後,把檔案字尾改為.cginc。當然,作業系統一般會給你一些警示資訊,說這個檔案將變得不可用,但相信我,我們這個是可用的。
- 將新的.cginc檔案匯入到我們的Unity專案中(注意,在我的專案裡,它的位置在一個新的名為CgIncludes的資料夾下)。等編譯完成後,我們可以看到Unity把該檔案當成一個CgInclude檔案編譯好了。像下面這樣:
實現
開啟CgInclude檔案後,開始鍵入如下程式碼。- 首先,使用下面的預處理指令開始我們的CgInclude檔案。這些宣告和#pragma、#include類似,在這裡,我們想要去定義一個新的程式碼集合,只要我們的Surface Shader在它的編譯指令裡面包含了這個檔案,這些程式碼就可以執行了。在CgInclude檔案的最開始鍵入如下程式碼:
#ifndef MY_CG_INCLUDE #define MY_CG_INCLUDE
- 然後,我們必須確保#ifndef或者#ifdef要有一個#endif來結束定義檢查。就和一個if語句需要兩個花括號一樣。在#define指令下面鍵入如下程式碼:
#endif
- 接下來,我們就可以填充剩餘部分了。鍵入如下程式碼:
// Custom Build-in Variables fixed4 _MyColor; // Lighting models inline fixed4 LightingHalfLambert (SurfaceOutput s, fixed3 lightDir, fixed atten) { fixed diff = max (0, dot (s.Normal, lightDir)); diff = (diff + 0.5) * 0.5; fixed4 c; c.rgb = s.Albedo * _LightColor0.rgb * ((diff * _MyColor.rgb) * atten * 2); c.a = s.Alpha; return c; }
- 下面是完整的MyCgInlcude.cginc檔案:
#ifndef MY_CG_INCLUDE #define MY_CG_INCLUDE // Custom Build-in Variables fixed4 _MyColor; // Lighting models inline fixed4 LightingHalfLambert (SurfaceOutput s, fixed3 lightDir, fixed atten) { fixed diff = max (0, dot (s.Normal, lightDir)); diff = (diff + 0.5) * 0.5; fixed4 c; c.rgb = s.Albedo * _LightColor0.rgb * ((diff * _MyColor.rgb) * atten * 2); c.a = s.Alpha; return c; } #endif
上面相當於一個頭檔案,但想要完整利用它還需要一些其他的步驟。我們需要告訴當前的Shader,我們想要使用自己的檔案和程式碼。 - 返回上一節所用的Shader。我們需要在塊中包含我們自己的CgInclude檔案,就像C++中需要在開頭新增標頭檔案引用一樣。同時,之前我們的Shader使用內建的Lambert光照模型,但現在我們想要使用自定義的Half Lambert光照模型。因為我們已經包含了該CgInclude檔案,我們可以直接在#pragma指令中指明這一模型:
CGPROGRAM #include "../CgIncludes/MyCgInclude.cginc" #pragma surface surf HalfLambert
解釋:這裡需要指明.cginc檔案的相對與該Shader的路徑。也就是說,如果它和Shader放在同一個資料夾下,那麼直接寫名稱即可。但在我的專案中,Shader放在了Shaders資料夾下,而.cginc放在了CgIncludes資料夾下,因此需要上述寫法。 - 最後,還記得我們在CgInclude檔案中聲明瞭一個_MyColor變數嗎?我們還需要在Shader的Properties中新增該屬性:
Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _DesatValue ("Desaturate", Range(0, 1)) = 0.5 _MyColor ("My Color", Color) = (1, 1, 1, 1) }