unity shader淺析

simaoshid1 2018-06-22

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)

unity shader淺析

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.

unity shader淺析

發表評論

發表評論:

17601037727 1280857492