Shader理論《四》概述以及結構

一.Unity Shader概述

1.在Unity中我們需要配合使用材質(material)和Unity Shader才能達到需要的效果。材質是載體,Unity Shader是文本文件,我們在Unity Shader中寫好渲染的代碼(屬性,頂點着色器,片元着色器等),加載到材質上,在材質上可以調節shader的屬性,然後將材質賦給模型展示渲染效果。

2.Unity Shader不是傳統意義上的的Shader,Unity Shader實際上指的是一個ShaderLab文件--以.shader爲文件後綴的一種文件。但Unity Shader可以做的遠多於一個傳統意義的Shader。

a、傳統Shader中,我們只可以編寫特定類型的Shader,比如頂點着色器,或片元着色器等。Unity Shader中我們可以在一個文件中編寫他們。

b、傳統Shader中,我們不能做一些例如開啓混合、深度測試等渲染測試,這是在另外的代碼中設置的。Unity Shader中我們加幾個指令就可以了。

c、傳統Shader中,需要編寫大量代碼設置着色器的輸入和輸出。Unity Shader中,我們只需要聲明一些屬性,並可以在材質中改變這些屬性。對於模型數據(頂點位置,紋理座標,法線,切線等),Unity Shader中我們可以直接訪問,傳統Shader需要自行編碼傳給shader。

d、Unity Shader的高度封裝,使其失去了更多的編寫自由性,不過同時也使我們只需要和Unity Shader打交道,不用關心渲染引擎底層實現。

3.Unity 5.5版本中,提供了5種Unity Shader模板:Standard Surface Shader,Standard Surface Shader(Instanced),Unlit Shader,Image Effect Shader, Compute Shader。

a、Standard Surface Shader是基於物理渲染(PBS)的包含標準光照模型的表面着色器模板,在5.x版本中,我們新建一個材質,它會默認使用內置的Standard Shader,是使用基於物理渲染(PBS)的技術,區別於傳統光照Shader,它對光照渲染有着更加強大的支持,當然如果想達到強大的效果,除了主紋理和法線紋理,你可能需要加入金屬紋理,粗糙度紋理,遮擋紋理,細節紋理,並配置一堆屬性,再加上光照探針,反射探針啥的,想清楚再用。

b、Standard Surface Shader(Instanced),據說是5.4版本以後加的,使用了Gpu Instancing技術,這個技術在大量使用相同材質和網格的情況下可以大幅度降低Draw Call,而這個模板在生成陰影pass中使用了該技術。

c、Unlit Shader:不包含光照但包含霧效的頂點片元着色器。

d、Image Effect Shader:只是一個簡單的圖片展示效果,爲實現屏幕後處理效果提供了基本模板。

f、Compute Shader:產生特殊的shader文件,旨在利用GPU的並行性來進行一些與常規渲染流水線無關的計算。(原書照搬,不在研究範圍)。

a和b是表面着色器,c和d是頂點片元着色器,請對應選擇模板。(因爲喜歡用頂點片元着色器,我喜歡用d)

 

二.ShaderLab

上面提到過Unity Shader不是傳統意義的shader,編寫傳統意義的shader需要和很多文件和配置打交道,Unity爲我們提供了一層抽象:Unity Shader,而專門爲Unity Shader服務的語言就是ShaderLab。

 

三.Unity Shader結構

1.名字

每個Unity Shader第一行都需要定義一個名字,格式例子:Shader "Custom/MyShader","/"是路徑,其對應位置爲Shader->Custom->MyShader。

2.屬性(Properties)

Properties {

Name ("display name", PropertyType) = DefaultValue

Name ("display name", PropertyType) = DefaultValue

....

}

Properties中包含了一系列屬性,會在材質面板中展示,開發者可以方便調試它們,同時shader會訪問它們,類似於untiy的public變量。如上所示,每條屬性由Name(名字,代碼中要用),"display name"(面板顯示名字),PropertyType(屬性類型),DefaultValue(默認值)組成。Unity Shader屬性類型如下:

3.SubShader

一個Shader文件可以包含多個SubShader,但最少要一個。Unity加載該shader時,會掃描並選擇一個能在目標平臺運行的SubShader,如果都不支持,會使用Fallback指定的Unity Shader。

SubShader通常定義如下:

 

[html] view plain copy
 
  1. SubShader {  
  2.     //可選  
  3.     [Tags]  
  4.     //可選  
  5.     [RenderSetup]  
  6.   
  7.     Pass {  
  8.     }  
  9.     //其他Pass  
  10.     ...  
  11. }  

 

 

 

a、Tags:標籤,由一組鍵值對組成,鍵和值都是字符串,它們告訴Unity渲染引擎,我希望怎樣及何時渲染該SubShader。結構如下:

Tags { "TagName1" = "Value1"  "TagName2" = "Value2"}

新手注意,每個標籤間隔不要加逗號或分號,只是空格,最後也沒符號,新手這裏容易寫錯。

SubShader支持的標籤類型如下(書上截圖,原諒我懶):

注意,這裏的標籤是在SubShader裏的,不是Pass裏的,它們不同。

b、RenderSetup

狀態設置,ShaderLab提供了一系列渲染狀態的設置指令,可以設置在SubShader裏,影響其下所有pass,也可以放某個pass裏,隻影響該pass。常見的渲染設置如下(接着截圖):

c、Pass

SubShader中可以有多個pass,每個Pass定義了一次完整的渲染流程,但Pass過多會造成渲染性能下降,所以我們儘量用最少數目的Pass。

Pass包含的語義如下:

 

[html] view plain copy
 
  1. Pass {  
  2.     [Name]  
  3.     [Tags]  
  4.     [RenderSetup]  
  5.     //正式代碼  
  6.     ....  
  7. }  


Name:該pass名字,可選,書寫例子如下:

 

Name "MyPassName"

通過該名字,我們可以在其他的Unity Shader中用UsePass命令直接使用該Pass,非常方便,例如

UsePass "MyShader/MYPASSNAME"

需要注意的是Unity內部會把所有Pass名稱轉換成大寫字母,所以用UsePass時必須使用大寫形式的名字。

上面SubShader的RenderSetup(狀態設置)同樣適用於Pass。

Pass的標籤不同於SubShader的標籤,下面是Pass中使用的標籤:

還有一些特殊的Pass

UsePass:前面提到了,可以用Pass的名字複用訪問。

GrabPass:該Pass負責抓取屏幕並存到一張紋理中,後面的Pass可以對該紋理繼續處理。

d、FallBack

放在最後,當所有SubShader都不合適,就用FallBack提供的Shader。語義如下:

FallBack "name" 或 FallBack Off

不要以爲它沒用,當你學到陰影那裏就知道它的用處了,FallBack的內置shader往往包含一個通用的陰影投射Pass,所以你不用自己實現。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章