1. 程式人生 > >Shader學習筆記(1):Shader基礎

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旁邊的下拉按鈕來看它當前編譯的平臺,你也可以更改要編譯的平臺。如下圖:

但當釋出遊戲時,遊戲資料檔案中只包含目標平臺需要的編譯程式碼,其他平臺的程式碼會被移除。