Shader學習筆記(1):Shader基礎
最近想學Shader,找到一個大佬的部落格,該筆記只是自己學習Shader的知識記錄,其實跟部落格的內容差不多,但是寫一遍,自己對shader的基礎更加清楚,這將是一個系列筆記,大佬部落格的地址:
1.unity提供的5種Shader模板
(1)Standard Surface Shader
基於物理渲染(PBS)的包含標準光照模型的表面著色器模板,在5.x版本中,我們新建一個材質,會預設使用unity內建的Standard Surface Shader,是使用基於物理渲染的技術,區別於傳統的光照Shader,對光照渲染有更大的支援,如果想達到強大的效果,出了主紋理和法線紋理,可能需要加入金屬紋理,粗糙度紋理,遮擋紋理,細節紋理,並配置一堆屬性加探針啥的
(2)Standard Surface Shader(Instanced)
5.4版本後加的,使用GPU Instancing技術,在使用相同材質和網格的情況下可以大幅度降低Draw Call,在生成陰影Pass中使用了該技術。
(3)Unlit Shader
不包含光照但包含霧效的頂點片元著色器。
(4)Image Effect Shader
簡單的圖片展示效果,為實現屏幕後處理效果提供了基本模板。
(5)Compute Shader
產生特殊的Shader檔案,利用GPU的並行性來進行一些與渲染流水線無關的計算。
(1)(2)-----------表面著色器
(3)(4)-----------頂點片元著色器(要學的)
2.ShaderLab——unity Shader的語言
3.Unity Shader結構
(1)名字
每個shader第一行需要定義一個名字,格式如:Shader "Hidden/ImageShaderTest",對應的路徑:Hidden->ImageShaderTest
(2)屬性(properties)
Properties{
Name("display name",type)=value
Name("display name",type)=value
................
}
Name---屬性名字,程式碼用的 display name---面板中顯示的名字 type--屬性型別 value:預設值
Properties包含了一系列屬性,類似類中的public變數,屬性型別如圖:
程式碼如:
(3)SubShader
一個Shader檔案可以包含多個SubShader,但至少要有一個。Unity載入Shader時,會掃描並選擇一個能在目標平臺執行的SubShader,如果都不支援,會用Fallback指定的Shader.
SubShader{
//可選(標籤)
[Tags]
//可選(狀態)
[RenderSetup]
Pass{}
//其他Pass
....................
}
A.Tags:標籤,由一組鍵值對組成。鍵和值都是字串,他們告訴Unity渲染引擎,希望怎樣及何時渲染該SubShader,結構如下:
Tags{"TagsName1"="Value1" "TagsName2"="Value2"}
兩個Tags之間不要加逗號或分號,只用空格分離
SubShader支援的標籤型別如下:
B.RenderSetup:狀態設定,
ShaderLab提供了一系列渲染狀態的設定指令,可以在SubShader裡,影響其下所有的Pass,也可以放在某個Pass下,隻影響該Pass,常見指令如下:
C.Pass
SubShader中可以有很多Pass,每個Pass定義了一次完整的渲染流程,但pass過多會造成渲染效能下降,儘量使用最少數目的Pass。
Pass{
[Name]
[Tags]
[RenderSetup]
//程式碼
.........
}
Name-----pass名字 Name“MyPassName”,可以使用UsePass "MyShader/MYPASSNAME"在其他Shader中直接使用該pass。UsePass指令使用時pass名字必須使用大寫形式的名字,因為unity內部會把所有的pass名稱轉換成大寫字母。
RenderSetup使用方式同於SubShader中的
Tags在pass中的標籤如下圖:
一些特殊的Pass:
a.UsePass:可以用Pass的名字複用訪問
b.GrabPass:該pass負責抓取螢幕並存到一張紋理中,後面的pass可以對該紋理繼續處理
D.FallBack
放在最後,當所有的SubShader都不適合,就用FallBack提供的Shader。
FallBack"shaderName"或者 FallBack Off
FallBack的內建shader往往包含一個通用的陰影投射Pass,所以你不用自己實現。
SubShader例子:
4.Unity Shader種類
(1)表面著色器
Unity自己創造的一種著色器程式碼型別,少量的程式碼可以實現很大的功能,但其實它擴充套件開了就是頂點/片元著色器,只不過Unity替你封裝好了很多程式碼,這樣反而渲染代價比較大。
(2)Vertex/Fragment Shader(頂點/片元著色器)
我們主要學習的著色器,可以使用Cg/HLSL語言來編寫,相對錶面著色器複雜一些,但靈活性更高。
(3)Fixed Function Shader(固定函式著色器)
5.CG/HLSL, GLSL
HLSL-----------DirectX,High Level Shading Language
GLSL------------OpenGL,OpenGL Shading Language
CG-------------NVIDIA,C for Graphic
我們看到上面的Surface Shader和Vertex/Fragment Shader的程式碼示例,發現核心程式碼都放在CGPROGRAM和ENDCG之間,其實它們是在ShaderLab內部巢狀的CG/HLSL語言,因為CG和DX9風格的HLSL從寫法上幾乎是一樣的,所以在Unity裡CG和HLSL是等價的。我們也可以用GLSL來寫,但釋出平臺會少一些,GLSL要巢狀在GLSLPROGRAM和ENDGLSL之間。
通常,Unity會自動把這些CG片段編譯到所有相關平臺上(D3D9,D3D11,OpenGL ES等),我們可以通過點選shader面板上的Compile and show code旁邊的下拉按鈕來看它當前編譯的平臺,你也可以更改要編譯的平臺。如下圖:
但當釋出遊戲時,遊戲資料檔案中只包含目標平臺需要的編譯程式碼,其他平臺的程式碼會被移除。