0x00 寫在前面
之前一直在閱讀 The Book of Shaders 一書,為什麼會開始寫 Unity Shader 呢?一方面,因為該書目前尚未完結,寫下此文時已閱讀到該書的最新章節;另一方面,也需要通過一些實踐來檢驗以及鞏固所學的知識。Unity 引擎提供的環境正好是一個不錯的媒介。
本文沒有完整可運行的 Shader 代碼,只是簡單梳理一下 Unity Shader 的基本結構,為之後學習做鋪墊。
0x01 基本框架一段 Unity Shader 的基本結構如下:
Shader "Path/ShaderName"{ Properties {
}
SubShader { [Tags] [RenderSetup] Pass { Name "PassName" [Tags] [RenderSetup] } } Fallback "OtherShaderName" }0x02 名字Path/ShaderName 決定該 Shader 在選擇面板上所處的位置,很像文件的全路徑。例如,Shader "Path0/Path1/CustomShader" 將位於 Path0 → Path1 → CustomShader:
0x03 屬性
Properties 括號中定義的屬性將在材質面板上展示,可以方便地進行調節。
Properties{ Name("Display Name", Type) = DefaultValue }定義一個屬性,就像在 C 語言中定義一個變量一樣,只是格式稍有不同。在上面的代碼中,Name 是屬性的名字,Display Name 是用於展示在材質面板上的名字,Type 是屬性的類型,DefaultValue 是屬性的默認值。ps:其中 Name 常常以下劃線開頭,例如 _PropertiesName。
下面列出一些常用的屬性:
數字_Number0("Number 0", Range(-2.0, 2.0)) = 0.0_Number1("Number 1", Float) = 0.618_Number2("Number 2", Int) = 3其中,Range 將在面板上展示一個滑動條,它的兩個參數依次表示可以滑動的最小值和最大值。Float 是浮點數,Int 是整數。
顏色和向量
_Color("Color", Color) = (1, 1, 1, 1)_Vector("Vector", Vector) = (1, 1, 1, 1)顏色 Color 的四個值分別表示 RGBA,在面板上將會展示修改按鈕以及吸取按鈕。向量 Vector 為四維向量,在面板上展示為 XYZW 四個格子。
紋理
_2DTexture("2D Texture", 2D) = "defaulttexture" {}_Cube("Cube", Cube) = "defaulttexture" {}_3DTexture("3D Texture", 3D) = "defaulttexture" {}2D 表示 2D 紋理貼圖,Cube 表示立方體貼圖,3D 表示 3D 紋理貼圖。它們都有 Tiling 和 Offset。
在 Properties 中定義的屬性可以在 SubShader 的代碼塊中使用,只需要在相應的地方定義與這些屬性 名字相同、類型匹配 的變量即可。SubShader 中的類型與 Properties 中的稍有不同,下面列出兩者對應的匹配關係:
SubShader 代碼中,有的屬性也可以不在 Properties 中定義,兩者都可以在運行時通過 C# 腳本動態地進行修改(如,使用方法 Material.SetFloat 修改浮點屬性)。兩者的區別是,定義在 Properties 中的屬性在修改後將會被保存,而不在 Properties 中的屬性則不會。
0x04 SubShader每個 Unity Shader 中都可以包含多個 SubShader,當 Unity 展示一個 Mesh 時,將會從這些 SubShader 中找到第一個可以運行的來運行。因為不同的硬體對 Shader 的支持不同,這裡可以理解為
0x05 TagsTags 是 kv 結構,用來指定 Shader 怎樣以及何時渲染對象。
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }關於 Tags 的詳細說明可以查看:ShaderLab: SubShader Tags 。
0X06 RenderSetupRenderSetup 用來設置顯卡的渲染狀態。比如,設置剔除模式。
關於渲染狀態的詳細設置可以查看:ShaderLab: Pass 。
0x07 Pass在 SubShader 中指定的 RenderSetup 將會應用到所有 Pass 中,我們也可以在 Pass 中單獨指定。Pass 中的 Tags 與 SubShader 中的有所不同 ,主要用於控制該 Pass 中的環境光、頂點照明等,詳見:ShaderLab: Pass Tags 。
Pass{ Name "PassName" [Tags] [RenderSetup] }當用 Name 為 Pass 指定名字後,可以在其它地方復用這個 Pass。其中,Pass 名需要大寫。用法如下:
UsePass "ShaderName/PASSNAME"一個 SubShader 中可以有多個 Pass,這些 Pass 將會被依次執行。
0x08 Fallback如果所有 SubShader 都無法使用時,將會嘗試使用 Fallback 指定的著色器。如:
0X09 總結本文簡單梳理了一下 Unity Shader 的基本結構,因為了解不深,部分內容只能粗略帶過。這些內容在以後有需要時會再深入研究。
最後,再回顧一下 Unity Shader 的基本結構吧:
每個 Shader 都需要定義名字,格式為:
Shader "Path/ShaderName" {}。
在 Shader 的括號中,如果有需要,我們可以在 Properties 語義塊中定義材質的屬性。
每個 Shader 都包含多個子著色器 SubShader。
使用多個 SubShader 是因為不同的硬體對 Shader 的支持有所不同。
當實例運行時,引擎會幫我們找到第一個可以運行的 SubShader 來運行。
當所有的 SubShader 都不能運行時,則使用 Fallback 指定的 Shader。
每個 SubShader 包含多個 Pass,每個 Pass 表示一個渲染流程。
因為有的效果需要幾個渲染才能表現出來,這時候就需要使用多個 Pass 了。
SubShader 和 Pass 都可以通過一些語義 (Tags 和 RenderType) 來設置渲染狀態,Pass 還可以通過:
Name "PassName" 來指定 Pass 的名字。
參考資料:
[1] Shaders Overview
[2] Unity Shader入門精要
聲明:發布此文是出於傳遞更多知識以供交流學習之目的。若有來源標註錯誤或侵犯了您的合法權益,請作者持權屬證明與我們聯繫,我們將及時更正、刪除,謝謝。
作者:drnkcff
原文:https://www.cnblogs.com/drnkcff/p/13777001.html
More:【微信公眾號】 u3dnotes