Shader程序的基本結構
在代碼中學習吧,註釋都寫好了。
Shader "First Fantasy/Water/Water Diffuse"
{
//定義着色器屬性;
Properties
{
/*
格式:_Name("Display Name", type) = defaultValue[{options}];
{
_Name - 屬性的名字,變量名.
Display Name - 這個字符串將顯示在Unity的材質編輯器中作爲Shader的使用者可讀的內容
type - 這個屬性的類型,可能的type所表示的內容有以下幾種:
Color - 一種顏色,由RGBA(紅綠藍和透明度)四個量來定義;
2D - 一張2的階數大小(256,512之類)的貼圖。這張貼圖將在採樣後被轉爲對應基於模型UV的每個像素的顏色,最終被顯示出來;
Rect - 一個非2階數大小的貼圖;
Cube - 即Cube map texture(立方體紋理),簡單說就是6張有聯繫的2D貼圖的組合,主要用來做反射效果(比如天空盒和動態反射),也會被轉換爲對應點的採樣;
Range(min, max) - 一個介於最小值和最大值之間的浮點數,一般用來當作調整Shader某些特性的參數(比如透明度渲染的截止值可以是從0至1的值等);
Float - 任意一個浮點數;
Vector - 一個四維數;
defaultValue -定義了這個屬性的默認值。
Color - 以0~1定義的rgba顏色,比如(1,1,1,1);
2D/Rect/Cube - 對於貼圖來說,默認值可以爲一個代表默認tint顏色的字符串,可以是空字符串或者"white","black","gray","bump"中的一個
Float,Range - 某個指定的浮點數
Vector - 一個4維數,寫爲 (x,y,z,w)
{option} - 它只對2D,Rect或者Cube貼圖有關,在寫輸入時我們最少要在貼圖之後寫一對什麼都不含的空白的{},當我們需要打開特定選項時可以把其寫在這對花括號內。如果需要同時打開多個選項,可以使用空白分隔。可能的選擇有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一個,這些都是OpenGL中TexGen的模式。
}
*/
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTexColor ("Diffuse", Color) = (1,1,1,0.55)
_MainTexMultiply ("Multiply", Range(0,5)) = 1
_MainTexMoveSpeedU ("U Move Speed", Range(-6,6)) = 0.5
_MainTexMoveSpeedV ("V Move Speed", Range(-6,6)) = 0.5
}
SubShader
{
//硬件將通過判定這些標籤來決定什麼時候調用該着色器。;
/*
"Queue"="xxx" --- 指定渲染順序隊列
{
Background (1000) - 最早被調用的渲染,用來渲染天空盒或者背景
Geometry (2000) - 這是默認值,用來渲染非透明物體(普通情況下,場景中的絕大多數物體應該是非透明的)
AlphaTest (2450) - 用來渲染經過Alpha Test的像素,單獨爲AlphaTest設定一個Queue是出於對效率的考慮
Transparent (3000) - 以從後往前的順序渲染透明物體
Overlay (4000) - 用來渲染疊加的效果,是渲染的最後階段(比如鏡頭光暈等特效)
(PS:我們也可以指定自己的Queue值,寫成類似這樣:"Queue"="Transparent+100",表示一個在Transparent之後100的Queue上進行調用。
通過調整Queue值,我們可以確保某些物體一定在另一些物體之前或者之後渲染,這個技巧有時候很有用處。)
}
"RenderType"="Opaque" -- 渲染非透明物體
"RenderType" = "Transparent" -- 渲染含有透明效果的物體
"IgnoreProjector"="True" -- 不被Projectors影響
"ForceNoShadowCasting"="True" -- 從不產生陰影
*/
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
ZWrite Off
Alphatest Greater 0
Blend SrcAlpha OneMinusSrcAlpha
//Level of Detail的縮寫;
/*
在Unity的Quality Settings中我們可以設定允許的最大LOD,當設定的LOD小於SubShader所指定的LOD時,這個SubShader將不可用。
Unity內建Shader定義了一組LOD的數值,我們在實現自己的Shader的時候可以將其作爲參考來設定自己的LOD數值,這樣在之後調整根據設備圖形性能來調整畫質時可以進行比較精確的控制。
{
VertexLit及其系列 = 100
Decal, Reflective VertexLit = 150
Diffuse = 200
Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
Bumped, Specular = 300
Bumped Specular = 400
Parallax = 500
Parallax Specular = 600
}
*/
LOD 200
//一個開始標記,表明從這裏開始是一段CG程序;
CGPROGRAM
/*
聲明瞭我們要寫一個表面Shader,並指定了光照模型;
格式:#pragma surface surfaceFunction lightModel [optionalparams]
{
surface - 聲明的是一個表面着色器
surfaceFunction - 着色器代碼的方法的名字
lightModel - 使用的光照模型。
}
*/
#pragma surface surf Lambert
//!!!對於這段CG程序,要想訪問在Properties中所定義的變量的話,必須使用和之前變量相同的名字進行聲明。;
//sampler2D就是GLSL中的2D貼圖的類型,相應的,還有sampler1D,sampler3D,samplerCube等等格式。;
sampler2D _MainTex;
fixed4 _MainTexColor;
fixed _MainTexMultiply;
fixed _MainTexMoveSpeedU;
fixed _MainTexMoveSpeedV;
struct Input
{
//聲明瞭一個叫做uv_MainTex的包含兩個浮點數的變量。;
float2 uv_MainTex;
};
/*
計算輸出時Shader會多次調用surf函數,每次給入一個貼圖上的點座標,來計算輸出。
第二個參數是一個可寫的SurfaceOutput,SurfaceOutput是預定義的輸出結構,我們的surf函數的目標就是根據輸入把這個輸出結構填上。
SurfaceOutput結構體的定義如下:
struct SurfaceOutput
{
half3 Albedo; //像素的顏色
half3 Normal; //像素的法向值
half3 Emission; //像素的發散顏色
half Specular; //像素的鏡面高光
half Gloss; //像素的發光強度
half Alpha; //像素的透明度
};
SurfaceOutput o - 這個就是經過表面計算函數surf處理後的輸出
*/
void surf (Input IN, inout SurfaceOutput o)
{
fixed2 MainTexMoveScrolledUV = IN.uv_MainTex;
fixed MainTexMoveU = _MainTexMoveSpeedU * _Time;
fixed MainTexMoveV = _MainTexMoveSpeedV * _Time;
MainTexMoveScrolledUV += fixed2(MainTexMoveU, MainTexMoveV);
//tex2d函數,CG程序中用來在一張貼圖中對一個點進行採樣的方法,返回一個float4。;
half4 c = tex2D (_MainTex, MainTexMoveScrolledUV);
o.Albedo = c.rgb * _MainTexColor * _MainTexMultiply;
o.Alpha = _MainTexColor.a;
}
ENDCG
}
FallBack "Diffuse"
}