1. 程式人生 > >Unity shader教程-第三課:實踐!同一個shader,多個material。

Unity shader教程-第三課:實踐!同一個shader,多個material。

更多更及時的文章請關於98教育

這節課我們開始利用我們學到的Properties知識來改動程式碼,用一個shader實現如下圖的幾個不同的球體:

步驟:

  • 使用MonoDevelop開啟shader檔案
  • 保證Properties裡面是如下內容
_EmissiveColor ("Emissive Color", Color) = (1, 1, 1, 1)
_AmbientColor ("Ambient Color", Color) = (1, 1, 1, 1)
_SomeValue ("Coefficient", Range(0, 10)) = 2.5
  • 找到程式碼中的#pragma surface surf Lambert
    這一行,回車另起一行後加入下面的三行程式碼
float4 _EmissiveColor;
float4 _AmbientColor;
float _SomeValue;
  • 清除原來在這個地方的
sampler2D _MainTex;
  • 找到方法 void surf(Input IN, inout SurfaceOutput o),把裡面的內容改成
float4 c = pow((_EmissiveColor + _AmbientColor), _SomeValue);
	
o.Albedo = c.rgb;
o.Alpha = c.a;

為保證你做成的最後內容跟我的一樣,這裡是最後的shader程式碼

Shader "myDiffuse"
{
	Properties
	{
		_EmissiveColor ("Emissive Color", Color) = (1, 1, 1, 1)
		_AmbientColor ("Ambient Color", Color) = (1, 1, 1, 1)
		_SomeValue ("Coefficient", Range(0, 10)) = 2.5
	}
	
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert
		
		float4 _EmissiveColor;
		float4 _AmbientColor;
		float _SomeValue;
		
		struct Input
		{
			float2 uv_MainTex;
		};
		
		void surf (Input IN, inout SurfaceOutput o)
		{
			float4 c = pow((_EmissiveColor + _AmbientColor), _SomeValue);
			
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

到這裡,我們就可以儲存shader。回到Unity中。

回到Unity後,選中名字為myDiffuse的material,然後按下鍵盤上的Ctrl+D,複製出material,把它改名為myDiffuse2。同樣的方式,複製出myDiffuse3, myDiffuse4。這個方式,能讓我們製作出使用同一個shader的不同的四個material出來。

在Scene面板中,如果你沒有加滿4個sphere,可以現在新增。然後分別給這四個球拖入我們的myDiffuse、myDiffuse2、myDiffuse3、myDiffuse4這幾個material。

選中任意一個material,你可以在Inspector上選擇Emissive Color或者Ambient Color,也可以通過拖動滑動條來改動數值,改動的過程中可以看到Scene中的物體會隨你的改動而變化顯示。同時,雖然我們只寫了一個shader用到4個物體上,改動一個物體的material並不會影響到跟它使用不一樣的material的物體。也就是說,我們屬性裡的值,其實是存在於material中。在我們改變相關的值的時候,unity會把值存到material對應的檔案中,並在執行的時候,作為shader需要的引數送到shader中。由此,雖然我們只寫了一個shader,但是因為送入的引數不同,因此物體的表現也就不同(為那些好奇的人,這節課的附錄部分介紹了怎麼開啟material檔案的方式,可以看到儲存的內容)。

對於我們上面改動的程式碼的解釋

當你在Properties塊宣告一個新的屬性值的時候,你也就給shader提供了一種讓使用者通過Inspector面板調整內部值的方式。每個變數都會儲存下最後使用者修正的結果。但是,如果程式碼需要在SubShader{}這個塊中用到這些值,必須在這個塊中同時宣告同樣名字的變數,這個方式把我們在Inspector上的值和最後程式碼的值連結起來,形成一個整體。

一旦你在SubShader{}塊中宣告這些變數後,你就可以在surf()方法中使用到這些變量了。surf()方法中,我們用到的pow()方法是NVidia的cg語言提供的一個方法,unity shader可以用cg中的方法,這個方法跟其他語言中的pow類似,是“返回指定數字的指定次冪”。

附錄:

Unity提供了把一些檔案存成文字型的方式,我們可以利用這個方式來檢視material檔案的內容。

步驟:

  • 選單 Edit | Project Settings | Editor,會開啟如下的面板

  • 該面板的Asset Serialization中,Mode點開,選擇 Force Text
  • 等進度條完成任務
  • 硬碟上找到我們的myDiffuse材質(material)檔案(以.mat)結尾,用可以開啟文字檔案的軟體開啟(寫字本、Ultraedit、Notepad++都可以)
  • 檢視裡面的內容,我這裡的如下圖

圖中高亮的地方可以看到我們選擇的顏色值。