UnityShader 從入門到蓋棺(一)

GTA5

前言

  筆者我是一個最近在入門UnityShader的菜雞⊙﹏⊙∥。寫點東西鞏固自己的認知,順便看看能不能幫助到其他和我一樣想入門的人。

  我是以馮樂樂的《Unity Shader入門精要》來作爲我的入門教程的。在接下來的正文裏面,我會跳過一些前置知識相關。但這些東西十分重要,所以我會盡量給出一些鏈接,讓大家去了解。我主要是圍繞一個個實例,讓大家快速做出效果。

  所以如果大家有圖形學相關底子,也瞭解Unity的基礎操作,會更方便下面的學習。大家有疑問的,或者我有錯誤的,歡迎大家評論,一起學習進步。

  另外,我會把整個工程上傳到github。大家可以去下載到完整的項目。

前期準備

  • Unity 2019.3.9 (這是我現在使用的版本)
  • 一個編輯器(Rider, Sublime, VS甚至記事本都可以( ̄▽ ̄)")

初識Unity Shader

來到正文了,廢話不多說,我們先看一下本節完成後,你會得到一個怎樣的結果。

colorSphere1

好了,讓我們打開Unity。然後在Window->Rendering->Lighting Settings打開光照設置,把天空盒去掉(暫時不希望它影響我們)。在SkyBox Material那裏選擇None即可。

CloseSkyBox

我們直接創建一個Shaders文件夾,然後在裏面新建一個Unity Shader文件(右鍵->Create->Shader->Unlit Shader),命名爲1_SampleShader。Unlit Shader是一種無關照Shader,它暫時更適合我們入門學習。

CreateShader

然後我們用我們準備好的編輯器打開我們創建的Shader文件。來看一下Unity Shader的結構。

ShaderStruct

接下來,我們動手寫一個最簡單的Shader,先把Shader文件裏原來的內容全部刪掉

接着起個我們的名字(先按我的名字來,想秀的等看完教程╰( ̄ω ̄o))。

Shader "Unity Shader/C1/1_SimpleShader" {
	
}

然後直接定義一個SubShader和Pass語義塊(我們暫時不需要Properties塊,因爲我們暫時不需要在面板裏輸入任何變量)

	SubShader {
		Pass {
			
		}
	}

我們開始CG代碼片段的編寫。先定義一個由CGPROGRAM和ENDCG所包圍的片段(可以理解成前面都是在做設置,下面纔是真正的Shader代碼。CG意味着一種語法,它更像DX的HLSL Shader語法)

			CGPROGRAM
			
			ENDCG

然後我們進行兩個預處理指令,指定哪個函數是頂點着色器,哪個函數是片段着色器。

#pragma vertex vert // 指定vert函數是頂點着色器
#pragma fragment frag // 指定frag函數是片段着色器

然後我們定義頂點着色器函數。我們先讓這個函數只做普通的MVP變換。(MVP變換是渲染管線很重要的一個概念,我會在最後給出一些閱讀材料讓讀者去了解)

// float4是指一個4個分量的float類型
// 輸入一個float4,這個參數來源於POSITION
// 輸出一個float4,這個參數將會寫到SV_POSITION
float4 vert(float4 position:POSITION) : SV_POSITION {
	return UnityObjectToClipPos(position); //MVP變換
}

上面提到的POSITION和SV_POSITION大家可以理解爲是一塊存儲空間,Unity會把這段存儲空間裏的值賦值給你的變量,或者把你變量的值複製到對應存儲空間中。其中頂點着色器必須輸出SV_POSITION用於後續處理,片段着色器也必須輸出SV_Target來指定一個片段顏色。

然後我們定義一個不管怎樣都輸出紅色的片段着色器。

// fixed比float的精度要小,會更省內存。一般(-2,2)範圍的浮點數可以用fixed。
// 輸出一個fixed4,寫到SV_Target裏
fixed4 frag() : SV_Target {
    // 淺綠色,爲什麼要這種顏色。別問,我朋友說他喜歡綠。
	return fixed4(0.2, 1.0, 0.5, 1.0);
}

好了,現在我們一個最最最簡單的UnityShader已經寫完了。我們創建一個Material(右鍵->Create->Material), 然後在這個材質(Material)的控制面板裏選擇我們的Shader。(Unity Shader->C1->1_Sample), 我們可以看到這個路徑就是我們上面的Shader名字。

SelectShader

然後我們在場景裏創建一個球體,記得先reset一下。

resetSphere

把材質拖到球體上,我們就可以看到一個淺綠色的球體了。

GreenSphere

會不會發現有點成就感,但又沒意思(這垃圾效果,不寫也罷╰(‵□′)╯)。別急,畢竟我們還在入門嘛,都還沒蓋棺。

接下來我們用一下Properties,起碼可以讓我們指定顏色。在SubShader語義塊前面加回我們的屬性塊。

Properties {
	_MainColor ("main color", COLOR) = (0.2, 1.0, 0.5, 1.0)
}
  • _MainColor 是我們後面代碼裏面要用的變量名
  • “main color” 是Unity控制面板中能看到的名字
  • COLOR 是這個屬性的類型,COLOR是一個Float4
  • = 後面接的是默認值,用戶不選的話,默認就是綠色。沒錯,那種綠色

你會發現這時候,那個材質的控制面板已經允許我們選顏色了,但只是選了沒用而已,接着我們就把這個顏色用上去。

我們在預定義語句的後面加上我們的變量聲明

#pragma vertex vert
#pragma fragment frag

fixed4 _MainColor;

然後片段着色器裏,我們直接輸出我們這個顏色。

fixed4 frag() : SV_Target {
	return _MainColor;
}

好了,現在可以在材質面板裏選擇顏色來控制我們球體的顏色了。大家可以去選一下看看效果。

pickcolor

我選了一個我朋友更喜歡的深綠色。

當然,頂點着色器是可以給片段着色器傳遞參數的。
我們先在頂點着色器函數前定義一個結構體。

struct v2f { // vertex to fragment, 頂點着色器輸出到片段着色器
	float4 position : SV_POSITION;
	float3 worldPos : TEXCOORD0; // 世界空間下的頂點座標 
};

然後我們修改頂點着色器的輸出爲v2f,並且爲每一個分量賦值。

v2f vert(float4 position:POSITION) {
	v2f output;  // 聲明一個v2f變量
	output.position = UnityObjectToClipPos(position);
	// 用位置右乘一個model矩陣轉換到世界空間
	output.worldPos = mul(unity_ObjectToWorld, position).xyz;
	return output;
}

接着只要把片段着色器的輸入定義爲v2f變量,我們就可以用上頂點着色器輸出的值了(當然是經過插值的)。

// 把世界空間的位置當成顏色輸出,這也是Shader的一種Debug方法
fixed4 frag(v2f input) : SV_Target {
	return fixed4(input.worldPos, 1.0) * 2;
}

我們可以看到現在的效果是,我們得到了一個五彩斑斕的球。

ColorSphere

如果出現問題的,可以到GitHub上查看源碼。

結語

這裏我就結束了我的第一篇入門分享,之後的節奏大概是每週一更,也有可能多更,但儘量不停更 - -。大家有疑問的也歡迎評論懟我,我會盡量認真看,我寫錯的地方也會去糾正。

另外,我一直相信,只要人人都付出一點愛,我就會O(∩_∩)O嘿嘿嘿。

vxpay

鏈接

MVP變換:https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/

github地址:https://github.com/gjbian/Unity-Shader-Study

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章