Unity的shader學習1

先來看一段咱們項目常見的Shader代碼,這個是Vertex&Fragment shader,目前已經不經常使用了,不過仍是適合咱們理解一些基礎知識和理解一些比較老的shader 代碼。下次咱們再講unity主推的surface shaderhtml

 1 Shader "Custom/test"
 2  {
 3     Properties 
 4     {
 5         _MainTex ("Base (RGB)", 2D) = "white" {}
 6     }
 7 
 8     SubShader 
 9     {
10         Pass
11         {
12             Tags { "RenderType"="Opaque" }
13             
14             CGPROGRAM
15             #pragma vertex vert
16             #pragma fragment frag
17             #include "UnityCG.cginc"
18             uniform sampler2D _MainTex;
19 
20             struct VertexOutput
21             {
22                 float4 pos:SV_POSITION;
23                 float2 uv_MainTex:TEXCOORD0;
24             };
25 
26             VertexOutput vert(appdata_base input)
27             {
28                 VertexOutput o;
29                 o.pos = mul(UNITY_MATRIX_MVP,input.vertex);
30                 o.uv_MainTex = input.texcoord.xy;
31                 return o;
32             }
33 
34             float4 frag(VertexOutput i):COLOR
35             {
36                 float4 col =  tex2D(_MainTex,i.uv_MainTex);
37                 return col;
38             }
39 
40             ENDCG
41         }
42     } 
43     FallBack "Diffuse"
44 }

 

 第1行代碼的 Shader "Custom/test" 聲明瞭目錄結構,test是這個shader的名字。以後就能夠在材質上中找到對應的shaderapp

 第3-6行聲明瞭shader的能夠調節參數的地方。設置了以後,就能夠在Inspector面板中找到對應的變量。具體內容查看這裏.函數

 第8行的SubShader比較重要。一個Shader中能夠包含任意多個SubShader,可是隻有一個SubShader被顯卡選中並最終執行。顯卡會自動選擇一個最適合它自身性能的SubShader去執行。若是咱們寫的SubShader最後都沒有被選中,那麼就執行第25行的fallback 指定的shader。性能

 第10行的Pass也很重要,在一個SubShader中咱們能夠定義多個Pass,而Pass與SubShader不一樣,你寫的每個Pass都會按照順序所有執行一遍.咱們要在Pass中寫具體的着色器代碼,還有一點要提一下,在Unity主推的Surface Shader中是不能寫Pass的,由於在Unity的光照模型中他會自動定義一些Pass,因此也就再也不容許你額外寫了。spa

 第12行的 Tags { "RenderType"="Opaque" } 他是一種ShaderLab(UnityShader中除了CG之外的語法),給咱們提供好的可配置的一些選項,這些選項你能夠每一個Pass都寫一個,也能夠直接寫在SubShader下面讓全部Pass公共用一個配置。這裏面的RenderType = "Opaque"是告訴渲染設備,這個使用這個Shader的材質是一個不透明的物體,對應的還有Transparent透明物體等,這個標籤的功能須要跟ztest配合使用。比較重要的還有Queue標籤,它會改變物體被渲染的順序。具體看這裏,經常使用標籤的順序爲 Background is 1000, Geometry is 2000, AlphaTest is 2450,Transparent is 3000 and Overlay is 4000.code

 第14~40行被CGPROGRAM 和 ENDCG包含的部分纔是真正的CG代碼orm

 第15~16行的兩句話是告訴渲染設備頂點着色器(vertex)和片斷着色器(fragment)的名字是什麼,這是爲了讓顯卡在渲染的時候可以準確找到他們而必須聲明的.而咱們後面具體些着色器的時候也要用這個名字htm

 第17行#include "UnityCG.cginc"是由於Unity爲咱們提供大量的可用變量和常量,好比說一些空間變換矩陣,這樣子能夠提升咱們的開發效率,爲了使用他們你須要把這句話加上。在Unity4.0以後你能夠省略這句話了,他會被默認包含進來,不過爲了向下兼容仍是建議加上。blog

 第18行的uniform sampler2D _MainTex;咱們聲明瞭一個叫_MainTex變量,他的類型是sampler2D(也就是指可採樣的2D貼圖),前面的uniform意思是說這個變量是由外部賦值進來的,你會發現這裏的_MainTex和咱們的Properties中的_MainTex名字一致,前面說過了,經過這種方式咱們就能夠在着色器中使用在Properties中聲明的變量了。開發

 第20行~24行是聲明一個頂點着色器的輸出結構,它同時也是片斷着色器的輸入結構.每一個變量聲明最後都跟了一個像:SV_POSITION這樣的語法,這在CG中稱爲語義(semantic),簡單的理解就是顯卡設定了一些特定的寄存器,用來存放一些指定的特殊變量,在渲染時候若是須要用到的話就直接來取,這樣子可能處理起來更快。其中SV_POSITION是專門用來存放模型頂點在投影空間的座標的。TEXCOORD0能夠用來存聽任何你想存放的變量,在光柵化的時候這個變量會被插值 。相似於TEXCOORD0還有TEXCOORD1,TEXCOORD2等,具體個數看顯卡的性能.咱們在這個結構裏添加了兩個變量一個是頂點投影座標,這個是必須有的,另一個是頂點的紋理座標,用來貼圖用的。

 第26~32行 是頂點着色器的代碼部分,着色器(理解成函數就好了)的返回類型爲咱們剛纔聲明的返回結構,着色器名字就用咱們在CG代碼一開始經過#pragma 關聯的名字。

而參數這裏要注意一下了,頂點着色器接受的參數都是模型最原始的參數,也就是美術同窗指定的模型自己的一些參數,包括頂點的位置,法線,紋理座標,顏色等等.unity經過MeshRenderer等render組件把頂點信息傳遞給了Shader,可是在Shader中是經過語義(semantic)來關聯這些參數.

這個appdata_base是一個Unity爲咱們定義好的結構,就在咱們上面寫過的#include"UnityCG.cginc"包含進來.你能夠在Unity安裝目錄的/Editor/Data/CGIncludes文件夾裏面找打他看一看源代碼。

 因此在頂點着色其中咱們能夠經過appdata_base.XXX這種方式來直接獲取模型的頂點信息了。具體官方解釋查看這裏。Unity_Matrix_MVP是unity提供好的模型空間轉投影空間的矩陣,mul(UNITY_MATRIX_MVP,input.vertex)就能取到投影空間的座標。

 o.uv_MainTex = input.texcoord.xy;就是將uv信息傳遞進去。texcoord.xy就是uv信息。

第34~38行是片斷着色器的代碼,因爲片斷着色器的任務就是最後計算出一個顏色提供給渲染設備進行最後的處理,因此它的返回值爲float4(存的是rgba).

函數的名字與前面#pragma約定好的一致.參數的話就是剛剛頂點着色器輸出結構.

而最後面還跟了個:COLOR,這是爲了把返回結果提供給:COLOR語義關聯的寄存器,到時候渲染設備最後進行處理的時候去這裏取片斷着色器計算出來的結果就能夠了.

 tex2D函數,這是一個根據紋理座標查詢2D貼圖顏色的函數,第一個參數是貼圖,就是咱們在上面聲明的_MainTex,然後面是咱們要查詢的座標,紋理座標填上去就能夠了,最終將爲咱們返回一個貼圖上的顏色。

相關文章
相關標籤/搜索