我們已經建立了一些屬性,現在在着色器中開始試着把這些屬性用起來,通過這些屬性讓材質的微調過程更加高效。
可以通過材質的inspector标簽頁得到這些屬性的值,因為我們給屬性綁定了一個變量名。但是在通過變量名通路屬性值之前,要先準備一些東西。
下面是在表面着色器中使用屬性的步驟:
因為我們在1.2節中已經删除了_maintex,是以開始之前,先移除下面幾行代碼:

接下來,在着色器中的cgprogram行之下添加如下代碼:
第2步完成之後,可以在着色器中使用屬性的值了。我們先将_color屬性和_ambientcolor屬性的值相加之後,賦給o.albedo,是以在surf()函數中添加下面的代碼:
最終的着色器代碼應該看起來像下面這樣。如果你在monodevelop中儲存代碼然後在unity中打開,着色器會被自動編譯。如果沒有錯誤的話,可以修改材質的環繞色和發光色了,也可以通過滑塊來增加最終顔色的飽和度等值。就是這麼智能!
下載下傳示例代碼
pow(arg1, arg2)是一個内建函數,表示的是數學上的幂函數,第一個參數是底數,第二個參數是幂次數。
下面這張截圖是使用我們新添加的屬性,在inspector标簽頁微調了顔色和飽和度之後得到的結果。
當你在properties代碼塊中聲明一個新的屬性時,實際上是在給着色器提供一種擷取材質的inspector标簽頁中值的方式,這個值存儲在變量名對應的存儲單元中。在這個例子中,_ambientcolor、_color和 _myslidervalue就是所有我們用來存儲微調值的變量。為了能在subshader{}代碼塊中使用這些值,需要建立三個與屬性變量同名的變量。這樣就能給二者自動建立一種聯系,以便它們知道是在圍繞同一個資料做修改。此外,它還聲明了我們想存儲在子着色器變量中的資料類型 ,這也給我們日後的優化帶來了不少友善。
如果你建立了子着色器變量,就可以在surf()函數中使用它們了。在這裡,我們想将_color和 _ambientcolor變量加到一起作為幂函數的底,而将_myslidervalue變量作為幂函數的幂次數。
絕大部分着色器都是從标準着色器開始的,然後逐漸調整到想要的樣子。我們現在已經建立好了一個基礎的表面着色器,通過這個表面着色器你可以建立任何你想要的漫反射元件。
材質是資源的一種,也就意味着遊戲運作時任何一點針對材質的修改都是永久性的。如果你誤操作了某個屬性的值,可以通過ctrl + z來撤銷。
和其他的程式設計語言差不多,cg不允許代碼錯誤。此時,如果你的代碼中有筆誤,着色器是不會正常顯示的。如果發生了這種情況,你的材質會呈現無任何塗層的洋紅色:
如果腳本不能編譯,unity會阻止遊戲輸出甚至阻止遊戲運作。相反,着色器中的錯誤并不會阻止遊戲運作。
如果你的某個着色器呈現洋紅色,就要花點時間研究問題在哪裡了。如果選中出錯的着色器,會在inspector标簽頁中看到一個錯誤清單:
除了顯示出錯行之外,錯誤消息也同時在告訴你應該去這裡修複問題。上面截圖裡的錯誤資訊是在删除subshader{}代碼塊中的sampler2d _maintex變量的時候産生的。但是錯誤出現在首次想要通路這個變量的地方。
找到并且修複問題的過程稱為調試,大家常犯的錯誤如下:
少個括号。如果你在某個部分忘了一個反括号,編譯器會在這一部分文本的最後、最前或者某個新的部分處報錯。
少了分号。這是最為常見的一種錯誤,也是最容易發現和修複的。報錯資訊通常出現在下一行。
在properties代碼塊中定義了一個屬性,但是沒有在subshader{}代碼塊中标明為一個變量。
與c#腳本混淆了,cg中的浮點數并不需要在後面加一個f,比如1.0而不是1.0f。
着色器提供的報錯資訊可能非常難懂,特别是在某些有特别嚴格的文法限制的時候。如果你不懂報錯資訊的意思,最好在網上搜一搜。unity論壇裡面有很多開發者,他們很有可能碰到或者修複過你現在碰到的問題。
表面着色器及其屬性的更多内容放在第2章中。如果你想知道着色器火力全開的時候能做些什麼,可以看看第10章,這一章有本書中所覆寫的大部分進階着色技術。