關於Unity中Shader的基礎認識

Shader也叫着色器,是Unity裏面比較難的一個點,網上有很多別人寫好的shader,我們可以下載下來用或者修改學習。

Shader可以做出很多非常不錯的效果,因爲它是插在渲染管道里面的程序,一來是性能好,是GPU執行的,不需要CPU再去做額外的處理,二來就是可控性強,可以控制到每個頂點,每個像素的着色。

比如把一張圖片置灰,插入一個像素Shader,每個像素在紋理着色的時候把整個RGBA求一個灰度出來,這樣就變成一個灰色的圖片,這就是一個典型的像素Shader的使用。

 

Shader

1: Shader是給GPU執行的程序,中文叫做着色器;
2: 着色器是運行在圖形處理單元上,可以讓開發人員直接操作圖形硬件渲染功能;
3: shader能開發出很多好的效果,UV動畫,水, 霧 等一些特效, 這些用程序開發出來(cpu)比較困難,性能還不好;
4: 渲染流水線, 模型投影, 定點着色;
5: shader一般主要有: 固定管線着色器, 頂點片元着色器, 表面着色器;
固定管線着色器(慢慢會被淘汰);
頂點shader: 干預模型形態的shader; 
像素shader: 干預像素着色的shader;
6: 模型定點運算的時候,可以加入頂點shader來干預頂點的位置;
頂點着色的時候,加入像素shader來干預像素的上色;

 

UV動畫:在模型上面再貼一張圖,不斷地改變這個新貼圖的紋理座標,就產生不斷滾動的效果,就像cocos案例裏面烏龜在水裏遊,身體被波光覆蓋的那個動畫效果。

渲染流水線:一個3D模型拿到GPU裏面渲染,有一個工作流水線,正是因爲有了這些流水線,GPU才公開一些接口出來,方便程序員在流水線通道里面插入自己的代碼。也就是說支持用戶自己寫代碼插入流水線通道里面,來實現用戶需要的特殊效果。

頂點shader:模型頂點進來了以後,我們可以通過shader把頂點變換成另外一種形狀,比如我們有一個網格,是直來直去的那種,我們可以讓shader干預一下這個網格上的頂點,讓它變得彎彎的像波浪那種的樣子,再貼上紋理。     

      正弦波

像素shader:當我們成像上去後,要對點進行上色,哪個點要貼哪個紋理,所以需要對它們進行上色,上色的時候也可以用shader進行處理,比如剛纔的烏龜的UV動畫,把另外一個紋理和原來紋理結合。

      岩漿,本來做好了紋理的,但是是靜態的,我們可以通過動態地改變紋理座標,讓岩漿流動起來,實際上是改變了每個頂點着色的紋理座標

 

 

Direct3D和opengl

1: 什麼是Direct3D和opengl;
2: 目前面向GPU的編程語言主要有三種:
HLSL 語言 通過Direct3D編寫的着色器程序,只能在Direct3D裏面使用;
Cg 語言 NVIDIA和微軟合作提供的語言,與C相似,Direct3D和opengl都支持;
GLSL語言 支持OpenGL上編寫Shader程序;
3: Unity使用ShaderLab來進行着色程序的編寫,對不同的平臺進行編譯,重點支持Cg語言;

 

顯卡要支持Direct3D什麼什麼的......

Direct3D和opengl:PC發展史,PC實際上是繼承在操作系統上面的,PC上面有各種各樣的硬件在發展,如顯卡,顯卡就提出越來越多的把很多的圖形單元放在GPU上面運算,可是我的顯卡雖然支持這種計算,但是怎樣告訴程序,所以要把顯卡的功能做出一組API出來,公佈給程序使用。

 

現在有兩個端口,一個是操作系統是OS:Windows,Linux,一個是顯卡產商Nvidia,AMD,兩個顯卡產商,它們之間要怎麼統一標準,所以微軟提出來一個叫DirectX的標準,圖形的標準,裏面定義很多硬件加速的接口,顯卡產商就負責在顯卡驅動裏面來實現支持這些接口,所以當DirectX裝好了以後,我們的代碼使用DirectX的API,由於顯卡的驅動接好了底層的API的實現,所以API就能夠使用顯卡加速,來獲得很好的圖形性能,這就是爲什麼顯卡總要裝一個驅動,因爲它裝好驅動以後要把圖形圖像的接口統一起來接好,這樣通過DirectX就能訪問得到顯卡的硬件加速。

 

微軟DirectX不開源的,而Linux的OpenGL是開源的,安卓,Linux,IOS,都支持OpenGL,而不支持DirectX,微軟也支持OpenGL,大家在Windows上面習慣使用DirectX,在Linux上面習慣使用OpenGL

而Unity是跨平臺的遊戲引擎,所以在Windows上使用DirectX,,在Linux上使用OpenGL。

 

有了這兩個標準以後,顯卡產商就通過驅動的形式,把標準接入到標準庫裏面去,這樣應用程序只要調用API就能夠使用顯卡加速,如果有的話。

同時DirectX和OpenGL也支持用戶直接塞程序,比如塞shader給顯卡執行,所以GPU顯卡也有編程語言,有三種HLSL,Cg,GLSL語言

由於Unity是跨平臺的遊戲引擎,所以它重點支持cg語言,但是它又不直接使用cg語言,而是自己搞一個shaderLab語言來做着色程序的編寫,這樣我們就可以使用Unity的shaderLab的語法來生成各種各樣平臺不同的着色程序。

我們所說的shader就是使用Unity的shaderLab來編寫的着色程序。

 

 

Shader Lab語法基礎

1: 定義一個Shader,每一個着色程序都要有一個Shader
  Shader “name” { // name shader名字
  // 定義的一些屬性,定義在這裏的會在屬性查看器裏面顯示; 
  [Propeties] 
  // 子着色器列表,一個Shader必須至少有一個子着色器; 
  Subshaders: {....}
  // 如果子着色器顯卡不支持,就會降級,即Fallback操作;
  [Fallback]
}

 

 

Properties

1:name(“display name”, type) = 值;
  name指的是屬性的名字,Unity中用下劃線開始_Name;
  display name是在屬性檢查器的名字;
  type: 這個屬性的類型
  值: 只這個屬性的默認值;
2: 類型:
  Float, Int, Color(num, num, num, num)(0 ~ 1) Vector(4維向量), Range(start, end)
  2D: 2D紋理屬性;
  Rect: 矩形紋理屬性;
  Cube: 立方體紋理屬性;
  3D: 3D紋理屬性;
  name(“displayname”, 2D) = “name” {options}
3: Options: 紋理屬性選項
  TexGen:紋理生成模式,紋理自動生成紋理座標的模式;頂點shader將會忽略這個選項; 
  ObjectLinear, EyeLinear, SphereMap, CubeReflect CubeNormal
  LightmapMod: 光照貼圖模式如果設置這個選項,紋理會被渲染器的光線貼圖所影響。

 

例子

1: _Range (“range value”, Range(0, 1)) = 0.3; // 定義一個範圍
2: _Color(“color”, Color) = (1, 1, 1, 1); // 定義一個顏色
3: _FloatValue(“float value”, Float) = 1 // 定義一個浮點
4: _MainTex (“Albedo”, Cube) = “skybox” {TexGen CubeReflect} // 定義一個立方貼圖紋理屬性;

 

Fallback

1:降級: 定義在所有子着色器之後,如果沒有任何子着色器能運行,則嘗試降級;
2: Fallback “着色器名稱”;
3: Fallback Off;
沒有降級,並且不會打印任何警告;

 

 

SubShader

子着色器,裏面包含一個一個連接通道的管道的合集

1: SubShader {[Tags], [CommonState], Pass {} }子着色器由 標籤(Tags),通用狀態,通道列表組成,它定義了一個渲染通道列表,並可選爲所有通道初始化需要的通用狀態;

pass就是通道,就是流水線上面一個一個的通道,物體模型經過一個一個通道,最終把經過通道處理的物體繪製出來。
2: SubShader渲染的時候,將優先渲染一個被每個通道所定義的對象。
3: 通道的類型: RegularPass, UsePass, GrabPass,
4: 在通道中定義狀態同時對整個子着色器可見,那麼所有的通道可以共享狀態;

 

SubShader 語法

1: SubShader {
Tags {“Queue”, “Transparent” }
Pass {
Lighting Off // 關閉光照
....
}
}

 

Tags 

1: Tags {“標籤1” = “value1” “key2” = “value2”}
2: 標籤的類型:
Queue tag 隊列標籤;
RenderType tag 渲染類型標籤;
DisableBatching tag 禁用批處理標籤;
ForceNoShadowCasting Tag 強制不投陰影標籤;
IgnoreProjecttor 忽略投影標籤;
CanUseSpriteAtlas Tag,使用精靈圖集標籤;
PreviewType Tag預覽類型標籤;

 

Pass

通道,可以把一個一個的通道看成一個一個的盒子,物體經過盒子進行加工,然後出來,就可以了。

1: subshader 包裝了一個渲染方案,這些方案由一個個通道(Pass)來執行的,SubShader可以包括很多通道塊,每個Pass都能使幾何體渲染一次;
2: Pass基本語法:
Pass { [Name and Tags] [RenderSetup] [Texture Setup]}
Pass塊的Name引用此Pass,可以在其它着色器的Pass塊中引用它,減少重複操作,Name命令必須打大寫;

 

 

RegularPass 通道渲染設置

1: Lighting 光照: 開啓關閉定點光照 On/Off
2: Material{材質塊}: 材質,定義一個使用定點光照管線的材質;
3:ColorMaterial: 顏色集 計算定點光照的時使用頂點顏色;
4: SeparateSpecular: 開光狀態 開啓或關閉頂點光照相關的鏡面高光顏色,On/Off;
5: Color 設置定點光照關閉時的所使用的顏色;
6: Fog{霧塊}: 設置霧參數;
7: AlphaTest: Alpha測試
8: ZTest: 深度測試模式;
9: ZWrite: 深度寫模式;
10: Blend: 混合模式 SourceBlendMode, DestBlendMode, AlphaSourcesBlendMode, AlphaDstBlendMode;
11: ColorMask 顏色遮罩: 設置顏色遮罩,顏色值可以由RGB或A或0或R,G,B,A的組合,設置爲0關閉所有顏色通道渲染;
12: Offset偏移因子: 設置深度偏移;

 

UsePass特殊通道

1: UsePass: 插入所有來自其它着色器的給定名字的通道;
UsePass ”Shader/Nmae”, Name爲着色器通道;
UsePass “Specular/BASE” // 插入Specular中爲Bass的通道;

 

GrabPass
1: GrabPass {}: 一種特殊通道類型,他會捕獲物體所在的位置的屏幕的內容,並寫入一個紋理中,這個紋理能被用於後續通道中完成一些高級圖像特效,後續通道可以使用
_GrabTexture進行訪問;
2: GrabPass{“紋理名稱”} 捕獲屏幕內容到指定紋理中,後續通道可以通過紋理名稱來訪問;

 

 

Category分類

1:分類是渲染命令的邏輯組。例如着色器可以有多個子着色器,他們都需要關閉霧效果,和混合
  Shader “xxxx” {
  Categroy {
  Fog { Mode Off }
  SubShader {...}
  SubShader {...}
  }
}

發佈了56 篇原創文章 · 獲贊 61 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章