Unity3D Shader基礎教程

原文地址:http://bbs.9ria.com/thread-212557-1-1.htmlhtml

此教程將指引你如何創建本身的Shaders,讓你的遊戲場景看起來更好。Unity配備了強大的陰影和材料的語言工具 稱爲ShaderLab,以程式語言來看,它相似於CgFX和Direct3D的語法,它不僅紀錄基本的端點或者映像點(vertex/pixel)資 訊,也描述了材質所必要的一切資訊。編程

 

在unity材質檢視器中能夠看到Shaders的性質及多重shader(SubShaders)的描述,針對不一樣圖 形硬件,每一個描述也都完整的說明了圖形硬件的彩現狀態,fixed function pipeline如何設定、vertex/ fragment programs如何做用。 Vertex and fragment程序可使用高階Cg程式語言或低階shader組合。app

 

在這個教程中,咱們將描述如何使用fixed function與programmable pipelines兩種方式於ShaderLab中撰寫shaders,咱們假設讀者擁有基本的OpenGL或Direct3D彩現概念,並對cg有 fixed function與programmable pipelines的常識,HLSL或GLSL編程語言技術,一些Shader教程與參考文件可於NVIDIA以及AMD的開發站上取得。編程語言

 

創建一個新的shader有兩種方法,能夠由菜單Assets->Create->Shader新增,或複製一個既有的shader再進行編輯,新的shader能夠透過雙擊來啓動編輯畫面(UniSciTE)函數

 

下面開始介紹一個基礎的shader範例:工具

 

  1. Shader "Tutorial/Basic" {
  2. Properties {
  3. _Color ("Main Color", Color) = (1,0.5,0.5,1)
  4. }
  5. SubShader {
  6. Pass {
  7. Material {
  8. Diffuse [_Color]
  9. }
  10. Lighting On
  11. }
複製代碼


着色器:開始
性能

  1. }
  2. }
  3. Shader "Tutorial/Basic" {
  4. Properties {
  5. _Color ("Main Color", Color) = (1,0.5,0.5,1)
  6. }
  7. SubShader {
  8. Pass {
  9. Material {
  10. Diffuse [_Color]
  11. }
  12. Lighting On
  13. }
  14. }
  15. }
複製代碼


這個shader範例只是衆多shader中最基本的一個,它定義了一個顏色性質,名稱爲Main Color,並指定了玫瑰色的效果(red=100% green=50% blue=50% alpha=100%),在調用時會跳過Diffuse的材質設定(_Color)並開啓頂點光源。測試

 

要測試這個shader,你能夠創建一個新的材質,並於Shader下拉菜單選擇(Tutorial->Basic),再把這個新材質指定到物件上,拖拉材質檢視器的顏色表並查看其變化。是時候研究更復雜的事情了!this

 

假如你開啓一個既有的複合shader,剛開始看可能會以爲有點難,在開始之前,咱們將詳細說明unity內建的VertexLit shader。這個shader使用fixed function pipeline產生標準的per-vertex照明。編碼

 

  1. Shader "VertexLit" {
  2. Properties {
  3. 2
  4. _Color ("Main Color", Color) = (1,1,1,0.5)
  5. _SpecColor ("Spec Color", Color) = (1,1,1,1)
  6. _Emission ("Emmisive Color", Color) = (0,0,0,0)
  7. _Shininess ("Shininess", Range (0.01, 1)) = 0.7
  8. _MainTex ("Base (RGB)", 2D) = "white" { }
  9. }
  10. SubShader {
  11. Pass {
  12. Material {
  13. Diffuse [_Color]
  14. Ambient [_Color]
  15. Shininess [_Shininess]
  16. Specular [_SpecColor]
  17. Emission [_Emission]
  18. }
  19. Lighting On
  20. SeperateSpecular On
  21. SetTexture [_MainTex] {
  22. constantColor [_Color]
  23. Combine texture * primary DOUBLE, texture * constant
  24. }
  25. }
  26. }
  27. }
  28. Shader "VertexLit" {
  29. Properties {
  30. _Color ("Main Color", Color) = (1,1,1,0.5)
  31. _SpecColor ("Spec Color", Color) = (1,1,1,1)
  32. 3
  33. _Emission ("Emmisive Color", Color) = (0,0,0,0)
  34. _Shininess ("Shininess", Range (0.01, 1)) = 0.7
  35. _MainTex ("Base (RGB)", 2D) = "white" { }
  36. }
  37. SubShader {
  38. Pass {
  39. Material {
  40. Diffuse [_Color]
  41. Ambient [_Color]
  42. Shininess [_Shininess]
  43. Specular [_SpecColor]
  44. Emission [_Emission]
  45. }
  46. Lighting On
  47. SeperateSpecular On
  48. SetTexture [_MainTex] {
  49. constantColor [_Color]
  50. Combine texture * primary DOUBLE, texture * constant
  51. }
  52. }
  53. }
  54. }
複製代碼


全部的shaders都必須以Shader做爲開始,接着是這個shader的名稱(例如:VertexLit),這個名稱將會顯示於檢視器(Inspector)。全部的語法都必須放在{ }以內。

 

若是要把shaders放在unity的submenus下面,請使用斜線,例如:MyShaders/Test,你將 會看到有個submenu名爲MyShaders,下面有個shader名爲Test,或是像這樣MyShaders->Test在 Properties block下面接着的是SubShader block,每一個描述都在這個段落中

 


Properties
properties位於shader block一開始的位置,你能夠定義任何性質,這些性質將可在材質檢視器中編輯,在VertexLit的個範例中,properties block看起來像這樣:

 

2.jpg

 

properties block內的語法都是單行的,每個性質描述都由內名稱開始(例如:Color,MainTex),在後方的括弧號中所顯示的名字也會顯示於inspector檢視器上,在此以後,描述的是該性質的預設值:

shader_2.jpg


可用的性質類型請參考Properties Reference。預設值與性質有關,以color爲例,預設值應該由四個值組成。

 

如今咱們已經定義了四個性質,能夠開始撰寫實際的shader了在開始之前,先了解shader的結構是如何定義的。

 

不一樣的繪圖卡有不一樣的能力,例如:有的繪圖卡支援fragment programs但有些沒有,有些能夠一次處理四個貼圖?(four textures)其餘的可能只能處理兩個或一個,爲了要符合全部用戶的硬體需求,一個shader能夠包涵多個SubShaders,當unity在運 算shader時,它將詳細察看全部的subshaders並且使用硬體可支持的第一個。

 

  1. Shader "Structure Example" {
  2. Properties { /* ...shader properties... }
  3. SubShader {
  4. // ...subshader that uses vertex/fragment programs...
  5. }
  6. SubShader {
  7. // ...subshader that uses four textures per pass...
  8. }
  9. SubShader {
  10. // ...subshader that uses two textures per pass...
  11. }
  12. SubShader {
  13. // ...subshader that might look ugly but runs on anything : )
  14. }
  15. }
  16. Shader "Structure Example" {
  17. Properties { /* ...shader properties... }
  18. SubShader {
  19. // ...subshader that uses vertex/fragment programs...
  20. }
  21. SubShader {
  22. // ...subshader that uses four textures per pass...
  23. }
  24. SubShader {
  25. // ...subshader that uses two textures per pass...
  26. }
  27. SubShader {
  28. // ...subshader that might look ugly but runs on anything : )
  29. 6
  30. }
  31. }
複製代碼


此係統提供unity能夠支援現有全部的硬體並取得最佳的品質。它做到了,然而,結果是必須撰寫很長的shaders語法在每個SubShader block,你能夠設定彩現途徑的狀態;並定義彩現途徑自己。完整的SubShader語法請參照SubShader Reference章節
每一個subshader等因而一個途徑集。要對幾何物件進行彩現,至少必定要有一個途徑,內定的VertexLit shader裏面僅有一個途徑:

 

  1. view plaincopy to clipboardprint?
  2. // ...snip...
  3. Pass {
  4. Material {
  5. Diffuse [_Color]
  6. Ambient [_Color]
  7. Shininess [_Shininess]
  8. Specular [_SpecColor]
  9. Emission [_Emission]
  10. }
  11. Lighting On
  12. SeperateSpecular On
  13. SetTexture [_MainTex] {
  14. constantColor [_Color]
  15. Combine texture * primary DOUBLE, texture * constant
  16. }
  17. }
  18. // ...snip...
  19. // ...snip...
  20. 7
  21. Pass {
  22. Material {
  23. Diffuse [_Color]
  24. Ambient [_Color]
  25. Shininess [_Shininess]
  26. Specular [_SpecColor]
  27. Emission [_Emission]
  28. }
  29. Lighting On
  30. SeperateSpecular On
  31. SetTexture [_MainTex] {
  32. constantColor [_Color]
  33. Combine texture * primary DOUBLE, texture * constant
  34. }
  35. }
  36. // ...snip...
複製代碼


經過指令能夠定義一個特殊的方法,用來驅動繪圖硬體彩現指定的幾何物件

例如:上方語法中有一個Material block,定義了照明時所須要幾項固定參數。而指令LightingOn用來開啓該照明設備,SeperateSpecular On則是啓用Seperate做爲特殊鏡射效果。到目前爲止的全部命令,皆屬於支援OpenGL/Direct3D技術硬體自己可以使用的固定功能,您能夠 參考OpenGL紅皮書,能夠找到更多相關資料。

 

下一個命令是SetTexture,這是個很是重要的命令,這個命令能夠定義影像紋理如何混合、組合以及如何運用於咱們 的彩現環境裏,SetTexture一般跟隨於紋理的屬性名稱以後(咱們在這裏使用_MainTex ),接下來的combiner block也是定義紋理的應用方式,這個combiner block的命令會在螢幕顯示每個被執行的動做。

 

讓咱們開始了一個着色器的通常結構小回顧:

  1. Shader "MyShaderName" {
  2. Properties {
  3. // ... properties here ...
  4. }
  5. SubShader {
  6. // ... subshader for graphics hardware A ...
  7. Pass {
  8. // ... pass commands ...
  9. }
  10. // ... more passes if needed ...
  11. }
  12. SubShader {
  13. // ... subshader for graphics hardware B ...
  14. }
  15. // ... Optional fallback ...
  16. FallBack "VertexLit"
  17. }
複製代碼


最後,咱們在這裏引入一個新的命令:
FallBack "VertexLit"
回退命令可用於在着色結束,它告訴它應該使用着色若是從目前的着色沒有SubShaders能夠運行在用戶的圖形硬件。其效果是同樣的,包括在年末從後備 着色全部SubShaders相同。例如,若是你寫了顛簸映射着色,而後不要寫成一個很是基本的非凹凸映射的老顯卡你能夠回退到subshader內置 VertexLit着色。

 

該着色的基本構建塊,介紹了在第一渲染教程,而性能完整的文件,SubShaders並經過提供。阿建設 SubShaders快速方法是使用證在其餘着色器定義。該命令UsePass正是如此,因此你能夠重用一個整潔時尚着色器代碼。做爲一個例子下面的命令 使用的名稱,經過「基地」從內置的鏡面着色:

  1. UsePass "Specular/BASE"
複製代碼

 

着色:頂點和片斷程序

爲了UsePass爲了工做,這個名字必須考慮的一個傳遞但願使用。經過名稱內的命令給它一個名字:

  1. Name "MyPassName"
複製代碼


頂點和片斷方案
咱們描述了經過該只使用一個單一的紋理相結合的第一個教程指令。如今是時候證實咱們如何可以經過使用咱們的頂點和片斷方案。
當您使用頂點和片斷程序(即所謂「可編程管線」),大部分的硬編碼功能(「固定功能管線」)在圖形硬件已關閉。例如,使用一個頂點程序關閉標準3D變換, 燈光和紋理座標生成徹底。一樣地,使用任何一個片斷程序替換紋理相結合,將在SetTexture命令定義的模式,所以SetTexture命令是沒有必 要的。


寫做頂點/片段程序須要一個三維轉換,照明和協調空間 - 透徹的認識,由於你必須重寫固定功能是同樣的OpenGL的API將本身的建造。另外一方面,你能夠作更多比內置的!

 

利用ShaderLab Cg語言
在ShaderLab着色器一般用Cg語言嵌入「Cg的片斷着色器中的文本」的編程語言。 Cg的片斷被編譯成低級的統一着色器組裝編輯,最後着色是在你的遊戲的數據中包含的文件只包含這個低層次的組裝。

 

當您選擇一個項目視圖着色,檢查員Cg語言編譯後顯示,這可能有助於在調試援助着色文本。統一自動編譯的CG OpenGL和Direct3D的片斷,因此你的着色器,使用Cg的工做都將只。請注意,由於企業管治守則是由編輯編譯,你不能建立Cg的從腳本在運行時着色器。


通常來講,Cg的片斷放在裏面通行證塊。他們看起來像這樣:

  1. Pass {
  2. // ... the usual pass state setup ...
  3. CGPROGRAM
  4. // compilation directives for this snippet, e.g.:
  5. #pragma vertex vert
  6. #pragma fragment frag
  7. // the Cg code itself
  8. 2
  9. ENDCG
  10. // ... the rest of pass setup ...
  11. }
複製代碼


下面的例子演示了一個Cg的方案,使得對象的顏色正常人徹底着色:

  1. Shader "Tutorial/Display Normals" {
  2. SubShader {
  3. Pass {
  4. CGPROGRAM
  5. #pragma vertex vert
  6. #pragma fragment frag
  7. #pragma fragmentoption ARB_fog_exp2
  8. #include "UnityCG.cginc"
  9. struct v2f {
  10. V2F_POS_FOG;
  11. float3 color : COLOR0;
  12. };
  13. v2f vert (appdata_base v)
  14. {
  15. v2f o;
  16. PositionFog( v.vertex, o.pos, o.fog );
  17. o.color = v.normal * 0.5 + 0.5;
  18. return o;
  19. }
  20. half4 frag (v2f i) : COLOR
  21. {
  22. return half4( i.color, 1 );
  23. }
  24. ENDCG
  25. }
  26. }
  27. Fallback "VertexLit"
  28. }
複製代碼



當應用於一個對象,將圖像中的結果以下(若是您的圖形卡支持頂點和片斷的過程當中方案):

 

1.jpg


咱們的「平均值顯示」着色沒有任何屬性,包含一個是空的,除了單一的企業管治守則證單SubShader。最後,向在VertexLit着色器內置的定義後備。讓咱們解剖了部分企業管治守則的一部分:

  1. CGPROGRAM
  2. #pragma vertex vert
  3. #pragma fragment frag
  4. #pragma fragmentoption ARB_fog_exp2
  5. // ... snip ...
  6. ENDCG
複製代碼


整個Cg的片斷之間寫入CGPROGRAM和ENDCG關鍵字。在開始編譯指令#pragma指令給出:
#pragma vertex name告訴該代碼包含在給定的函數(垂直這裏頂點方案)。
#pragma fragment name告訴該代碼包含在給定的函數有關水土這裏(片段程序)。
#pragma fragmentoption name加上一個選項來編譯OpenGL的片斷方案。在這裏,咱們添加指數平方霧支持。

 

繼彙編指令只是普通企業管治守則。咱們首先包括一個內置的Cg的文件:
#include UnityCg.cginc

 

該文件包含經常使用UnityCg.cginc宣言等的着色器能夠保持較小的功能。該文件自己是統一內發現的應用:/應用程 序/統一/ Unity.app /目錄/ CGIncludes / UnityCG.cginc。在這裏,咱們將使用appdata_base結構,V2F_POS_FOG宏觀和PositionFog從該文件助手做用。 咱們能夠只定義它們直接在着色,不包括文件的過程。

接下來,咱們要定義一個片斷「頂點」結構(這裏命名爲v2f) - 什麼樣的信息是從頂點傳遞到片段程序。咱們經過標準的地位和霧參數和float3顏色參數。顏色將計算出的頂點程序和公正的片斷程序的輸出。

 

咱們的出發定義的頂點程序 - 垂直功能。在這裏,咱們在計算標準方法使用UnityCG.cginc輔助功能(位置和霧)輸入和輸出做爲一種顏色正常的:

  1. ! o.color = v.normal * 0.5 + 0.5;
複製代碼


正常的組成部分是-1 .. 1範圍內,而色彩在0 .. 1範圍內,因此咱們在規模和偏見的代碼高於正常。接下來,咱們定義一個片段程序 - 有關水土功能,只是顏色和產出計算爲alpha組件1:

  1. half4 frag (v2f i) : COLOR
  2. {
  3. return half4( i.color, 1 );
  4. }
複製代碼


就這樣,咱們的着色完畢!即便這樣簡單的着色器是很是有用的可視化網格法線。

 

固然,這種着色不響應全部燈光,而這其中,事情變得有點複雜,對渲染管線和光衰減有關詳細信息,參考網頁閱讀。
企業管治守則中使用着色性能當你定義的着色性能,你給他們一個像_Color或_MainTex名稱。要使用Cg語言你他們只須要定義一
個匹配的名稱和類型的變量。統一將自動設置Cg的變量的名稱與着色性能匹配。

下面是一個完整的着色器顯示的顏色調製紋理。固然,你能夠很容易地作一個紋理合成調用相同的,但問題是這裏只是爲了說明如何使用Cg的屬性:

  1. Shader "Tutorial/Textured Colored" {
  2. Properties {
  3. _Color ("Main Color", Color) = (1,1,1,0.5)
  4. _MainTex ("Texture", 2D) = "white" { }
  5. 5
  6. }
  7. SubShader {
  8. Pass {
  9. CGPROGRAM
  10. #pragma vertex vert
  11. #pragma fragment frag
  12. #pragma fragmentoption ARB_fog_exp2
  13. #include "UnityCG.cginc"
  14. float4 _Color;
  15. sampler2D _MainTex;
  16. struct v2f {
  17. V2F_POS_FOG;
  18. float2 uv : TEXCOORD0;
  19. };
  20. v2f vert (appdata_base v)
  21. {
  22. v2f o;
  23. PositionFog( v.vertex, o.pos, o.fog );
  24. o.uv = TRANSFORM_UV(0);
  25. return o;
  26. }
  27. half4 frag (v2f i) : COLOR
  28. {
  29. half4 texcol = tex2D( _MainTex, i.uv );
  30. return texcol * _Color;
  31. }
  32. ENDCG
  33. }
  34. }
  35. Fallback "VertexLit"
  36. }
複製代碼


這種着色結構是在前面的例子同樣。在這裏,咱們定義兩個屬性,即_Color和_MainTex。企業管治守則內咱們定義相應的變量:

  1. float4 _Color;
  2. sampler2D _MainTex;
複製代碼


訪問中看到着色性能更多信息,Cg語言。

 

頂點和片斷程序在這裏不作任何幻想;頂點程序使用從UnityCG.cginc的TRANSFORM_UV宏,以確保質 地規模與偏移是正確應用,並片段程序公正樣品的質地和顏色屬性的繁殖。請注意,由於咱們正在編寫咱們本身的節目片斷在這裏,咱們不須要任何 SetTexture命令。如何紋理着色器適用於徹底控制的片段程序。

摘要
咱們已經展現瞭如何定製着色器程序能夠在幾個簡單的步驟產生。雖然這裏的例子所示很簡單,沒有什麼阻止你寫任意複雜的着色器程序!這能夠幫助您採起統一充分利用,實現最佳的渲染效果。

完整的ShaderLab參考手冊在這裏。咱們也有一個陰影在forum.unity3d.com論壇,從而去那裏獲得你的着色器的幫助!編程快樂,享受團結和Shaderlab權力。

在這個block內咱們設定了一個顏色值,並命名爲_Color,咱們會在後面使用這個顏色

在下個命令,咱們指定如何混合紋理以及顏色值。咱們用Combine命令來混合其餘紋理或顏色,看起來像下面這樣:
Combine ColorPart, AlphaPart在這裏ColorPart與AlphaPart定義了混合的顏色(RGB)以及alpha值(A)個別的資料,假如AlphaPart 被省略了,那它將與ColorPart的資料做混合在咱們的VertexLit範例中:

  1. Combine texture * primary DOUBLE, texture * constant
複製代碼


這裏的texture來源是當前的紋理(_MainTex),它將與主要的顏色互相搭配(*),主色爲照明設備的顏色,它是由Material計算出來的 結果。最終是這兩個倍增後的結果會增長照明強度.aplha值(在逗號之後)是由constantColor倍增而得的結果。另外一個經常使用的混合模式稱爲 previous(在這個shader未使用),這是全部previous SetTexture的結果,而且能夠用來混合多種紋理和顏色。

 

3.jpg

相關文章
相關標籤/搜索