【Unity Shaders】學習筆記之表面着色器(三)

一、表面着色器

   1.1 簡介

  表面着色器代碼直接在SubShader中編寫,不需要使用Pass,編譯器會將代碼編譯到合適的Pass中

   1.2 標籤 

  硬件將通過判定標籤來決定什麼時候調用該着色器

  屬性RenderType:
  值Opaque:在渲染非透明物體時調用
  值Transparent:表示渲染含有透明效果的物體時調用
  例:Tags { "RenderType"="Opaque" }

   1.3 申明變量

#pragma surface surfaceFunction lightModel [optionalparams] //聲明寫一個表面Shader


名字 說明
surface 申明這是表面着色器
surfaceFunction 着色方法的名字,如surf,在下面會出現surf函數
lightModel 使用的光照模型,如Lambert(就是普通的diffuse)

頂點處理函數 -> 表面處理函數 -> 光照模型函數 ->顏色值
sampler2D _MainTex;

sampler2D就是GLSL中的2D貼圖的類型,相應的還有sampler1D,sampler3D,samplerCube等格式

提問:在property中已經定義過_MainTex了,這裏爲什麼又要聲明一次呢?
 答:這個shader是由兩個相對獨立的塊組成的,外層的屬性、回滾等是Unity可以使用和編譯的ShaderLab;CGPROGRAM...ENDCG代碼塊是一段CG程序。對於這段CG程序,要想訪問在Properties中定義的變量,必須使用和之前變量相同的名字進行聲明。sampler2D _MainTex; 再次聲明並鏈接了_MainTex,使得接下來的CG程序能夠使用這個變量

   1.4 函數定義

  在#pragma段已經指出了着色方法的名字叫做surf,這段surf代碼就是着色器的工作核心。着色器就是給定了輸入,然後給出輸出進行着色的代碼CG規定了聲明爲表面着色器的方法(這裏是surf函數)的參數類型和名字,因此我們沒有權利決定surf的輸入輸出參數的類型,只能按照規定寫。這個規定就是第一個參數是一個Input結構,第二個參數是一個inout的SurfaceOutput結構接下來分別介紹Input、SurfaceOutput結構。

   1.5 Input結構

  Input是需要我們去定義的結構,可以把所需要參與計算的數據都放到這個Input結構中,傳入surf函數使用作爲輸入的結構體必須命名爲Inputfloat和vec都可以在之後加入一個2到4的數字,來表示被打包在一起的2到4個同類型數,如float2表示由兩個float數構成的一個數據變量的訪問:可以只使用名稱來獲得整組值,也可以使用下標的方式(比如.xyzw,.rgba或它們的部分比如.x等)來獲得某個值。在CG程序中約定,在一個貼圖變量(如_MainTex)之前加上uv兩個字母,就代表提取它的uv值UV mapping的作用是將一個2D貼圖上的點按照一定規則映射到3D模型上,是3D渲染中最常見的一種頂點處理手段。

  1.5 SurfaceOutput結構

  着色函數已經定義好了輸出結構,但內容是空白的,需要向裏面填寫輸出,這樣就可以完成着色了

truct SurfaceOutput {
half3 Albedo; //像素的顏色,反射值
half3 Normal; //像素的法向值
half3 Emission; //像素的發散顏色
half Specular; //像素的鏡面高光
half Gloss; //像素的發光強度
half Alpha; //像素的透明度
};
half指的是半精度浮點數,精度最低,運算性能相對比高精度浮點數高一些,因此被大量使用

  1.5 表面着色函數

  在計算輸出時Shader會多次調用surf函數,每次給入一個貼圖上的點座標,來計算輸出,然後把輸出結構填上函數tex2d:這是CG程序中用來在一張貼圖中對一個點進行採樣的方法,返回一個float4。這裏對_MainTex在輸入點上進行了採樣,並將其顏色的rbg值賦予了輸出的像素顏色,將a值賦予透明度。於是,着色器就明白了應當怎樣工作:即找到貼圖上對應的uv點,直接使用顏色信息來進行着色Unity中cg函數的路徑: C:\ProgramFiles\Unity\Editor\Data\CGIncludes ,查看UnityCG.cginc文件

二、代碼示例

1.在Unity編輯器的Project面板上,點擊Assets文件,選擇Create|Folder,命名爲Materials
2.創建另一個文件夾Create|Shader
3.創建一個Shader文件 命名爲BasicDiffuse 如下圖

4.創建一個材質球 命名爲BasicDiffuse 如下圖


5.雙擊BasicDiffuse着色器,打開MonoDevelop,你會看到Unity已經爲我們添加了一些基本的着色器代碼。
Shader "liulongling/BasicDiffuse" {
	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"
}
6.現在我們需要給着色器一個自定義文件夾路徑。着色器代碼中的第一行是對着色器的自定義描述,這樣我們可以在着色器的下拉列表中找到它,並且將它賦給在第四步創建BasicDiffuse材質球。如圖所示:


7.選中BasicDiffuse材質球,在Inspector面板點擊select,給它添加一張紋理圖片


8.創建3個Sphere,我們把BasicDiffuse材質球拖到其中一個Sphere上 看看有什麼效果
參考資料:
<<
Unity Shaders and Effects Cookbook>>

   作者:小毛驢,一個遊戲人 
   夢想:世界和平   
   原文地址:http://blog.csdn.net/liulongling
    
本博客中未標明轉載的文章歸作者小毛驢所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

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