Shader(著(zhe)色器)其實就是一小段程序,它負責将輸入的(de)網格或者貼圖顔色等信息,進行組合或者變換換之後将其輸出。之後再将寫好的(de)shader賦予材質,之後就可(kě)以由渲染器進行渲染。
Shader大(dà)體上可(kě)以分(fēn)爲兩類:表面著(zhe)色器(Surface Shader)和(hé)片段著(zhe)色器(Fragment Shader)。這(zhè)裏主要介紹表面著(zhe)色器。
我們先來(lái)看一段shader程序
Shader "Custom/Demo" { //shader的(de)分(fēn)類和(hé)命名
Properties{ //shader的(de)一些屬性
_MainTex("Texture",2D)="white"{}
_BumpMap("Bump Map",2D)="bump"{}
_RimColor("Rim Color",Color)=(0.26,0.19,0.16,0.0)
_RimPower("Rim Power",Range(1,10))=5.0
}
SubShader{
Tags { "RenderType" = "Opaque" }
LOD 200
CGPROGRAM //CG語言開始
#pragma surface surf Lambert //聲明(míng)光(guāng)照(zhào)模式
#pragma target 3.0
sampler2D _MainTex;
sampler2D _BumpMap;
float4 _RimColor;
float _RimPower;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
//從凹凸紋理(lǐ)獲取法線值
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
half rim = 1.0 - saturate(dot(normalize(IN.viewDir),o.Normal));
o.Emission = _RimColor.rgb*pow(rim,_RimPower);
}
ENDCG //CG語言結束
}
FallBack "Diffuse"
}
我們先來(lái)分(fēn)析Properties(屬性):
屬性的(de)語法定義是這(zhè)樣的(de)
_Name("Display Name", type) = defaultValue[{options}]
_Name:屬性的(de)變量名,之後代碼調用(yòng)需要這(zhè)個(gè)命名
Display Name:在unity編輯器裏面顯示的(de)名字
type:type大(dà)概有下(xià)面幾個(gè)種類
Color - 一種顔色,由RGBA四個(gè)量來(lái)定義;
2D - 一張2的(de)階數大(dà)小的(de)貼圖。這(zhè)張貼圖将在采樣後被轉爲對(duì)應基于模型UV的(de)每個(gè)像素的(de)顔色,***終被顯示出來(lái);
Rect - 一個(gè)非2階數大(dà)小的(de)貼圖;
Cube - 即Cube map texture,簡單說就是6張有聯系的(de)2D貼圖的(de)組合,主要用(yòng)來(lái)做(zuò)反射效果(比如天空盒)
Range(min, max) - 一個(gè)介于***小值和(hé)***大(dà)值之間的(de)浮點數,一般用(yòng)來(lái)當作調整Shader某些特性的(de)參數
Float - 任意一個(gè)浮點數;
Vector - 一個(gè)四維數;
defaultValue: 定義了(le)這(zhè)個(gè)屬性的(de)默認值,通(tōng)過輸入一個(gè)符合格式的(de)默認值來(lái)指定對(duì)應屬性的(de)初始值
Color - 以0~1定義的(de)rgba顔色,比如(1,1,1,1);
2D/Rect/Cube - 對(duì)于貼圖來(lái)說,默認值可(kě)以爲一個(gè)代表默認tint顔色的(de)字符串,可(kě)以是空字符串或者”white”,”black”,”gray”,”bump”中的(de)一個(gè)
Float,Range - 某個(gè)指定的(de)浮點數
Vector - 一個(gè)4維數,寫爲 (x,y,z,w)
***于***後一個(gè){options}隻對(duì)貼圖有關,這(zhè)個(gè)以後再說
所以上面那個(gè)shader在編輯器裏面看來(lái)是這(zhè)樣的(de)
Subshader 子著(zhe)色器
這(zhè)個(gè)暫時(shí)不詳細介紹
CG語言聲明(míng)接口
請允許我把它叫做(zuò)一個(gè)接口,上面我們在CG語言裏面再次聲明(míng)了(le)兩個(gè)變量,這(zhè)裏很多(duō)人(rén)就很奇怪,明(míng)明(míng)在屬性裏面已經聲明(míng)過了(le),爲什(shén)麽還(hái)要再次聲明(míng)一遍。這(zhè)裏的(de)sampler 2D就相當于是一個(gè)接口,我們可(kě)以通(tōng)過sampler2D來(lái)得(de)到一張圖的(de)像素與坐(zuò)标之間的(de)對(duì)應關系。這(zhè)樣就可(kě)以的(de)在CG語言裏面對(duì)其進行運算(suàn)。(注意:這(zhè)裏的(de)命名要和(hé)屬性裏面的(de)命名包保持一緻)
sampler2D _MainTex;
sampler2D _BumpMap;
Input
Input就是表面的(de)意思,輸入。這(zhè)是一個(gè)結構體,相信大(dà)家也(yě)不會陌生。也(yě)就是定義了(le)要向輸出函數裏面輸入什(shén)麽東西。
void surf (Input IN, inout SurfaceOutput o)
surf函數,也(yě)就是我們的(de)輸出函數。它的(de)兩有參數,***個(gè)是Input,在計算(suàn)輸出時(shí)Shader會多(duō)次調用(yòng)surf函數,每次給入一個(gè)貼圖上的(de)點坐(zuò)标,來(lái)計算(suàn)輸出。第二個(gè)參數是SurfaceOutput,SurfaceOutput是預定義的(de)輸出結構,surf函數的(de)目标就是根據輸入把這(zhè)個(gè)輸出結構填上。
SurfaceOutput結構體的(de)定義如下(xià):
struct SurfaceOutput{
half3 Albedo; //顔色
half3 Emission //發散顔色
half3 Normal //法向值
half Specular //鏡面高(gāo)光(guāng)
half Gloss //發光(guāng)強度
half Alpha //透明(míng)度
}
在上面的(de)例子中,我們設置了(le)它的(de)顔色,法線還(hái)有發散顔色。
FallBack "Diffuse"
很多(duō)人(rén)認爲,***後的(de)FallBack"Diffuse"隻是一個(gè)備胎,但其實并不是這(zhè)樣。我隻能引用(yòng)官方一句話(huà):A fallback statement has the same effect as if all subshaders from the other shader would be inserted into its place.
發表評論
發表評論: