2018年11月16日 星期五

Shader常用資料和連結

無論寫甚麼程式都經常要看網上資源和Documentation,Shader也一樣,但Shader的網上資源很鬆散,很多時連在Google搜尋也找不回自己以前見過的資料,於是我把一些常用的資料連結放在這裡,方便日後查閱。

Semantics

https://docs.unity3d.com/Manual/SL-ShaderSemantics.html

Microsoft對HLSL支援的每個Semantics有較詳細的解釋,但要注意Unity只支援一部分:
https://docs.microsoft.com/zh-tw/windows/desktop/direct3dhlsl/dx-graphics-hlsl-semantics

Semantics定義了一個Shader的輸入和輸出中包含了甚麼資訊。

常用的vertex shader的輸入Semantics包括:
  • POSITION:vertex在model space的位置,一般用float4
  • TANGENT:vertex在model space的tangent(切線),一般用float3
  • NORMAL:vertex在model space的normal(法線),一般用float4
  • TEXCOORD0-3:材質座標0-3(之後會用作uv mapping),一般用float2或4
  • COLOR:vertex顏色,一般用fixed4或float4

一邊來說vertex shader的輸出要有SV_POSITION (代表了vertex在clip space的位置),就算fragment shader裡面不需要用vertex位置來計算也要有,否則兩個Shader之間的步驟就無法計算vertex在screen上的位置。

如果fragment shader還需要其他資訊的話,就可以在vertex shader的輸出加多一點variable並配上適當的semantics(例如COLOR0-1代表顏色、TEXCOORD0-7代表uv mapping)。這些semantics的用途則完全是由我們決定(而非像vertex shader輸入,每個semantics代表了從Unity輸出的特定資訊)。

fragment shader的輸出一般都是SV_TARGET (每一粒pixel的顏色)。

CG datatype: float、half還是fixed?


到底應該用float、half還是fixed?

首先要知道每個datatype都有其範圍:
float:-3.4E38到3.4E38,7 significant digits
half:–60000到60000,3 significant digits
fixed:-2到2,1/256精準度(可以儲存color或unit vector)

如果你要儲存的數的範圍會超過的話就要升級成高級一點的datatype。一般來說可以用fixed就用fixed,不能再升級half或float,因為在某些較弱較舊的GPU上(尤其手機)fixed所需的memory是最低的(但實際上現在的手機一般half和fixed都用同樣的memory,而在PC上甚至三者也可能用一樣memory)。

ShaderLab Properties對應的CG datatype

https://docs.unity3d.com/Manual/SL-PropertiesInPrograms.html

Color、Vector:float4 half4 fixed4 (也可以只拿1-3)
Range、Float:float half fixed
2D、Cube、3D:sampler2D、samplerCube、sampler3D

Unity Shader內建library

library文件列表:https://docs.unity3d.com/Manual/SL-BuiltinIncludes.html
UnityCG.cginc的function列表:https://docs.unity3d.com/Manual/SL-BuiltinFunctions.html
下載原始碼:https://unity3d.com/get-unity/download/archive (選Unity版本後按Downloads→Built-in Shaders),在自己的電腦上也有(C:\Program Files\Unity\Editor\Data\CGIncludes)

HLSLSupport.cginc(包含跨平台用macro)和UnityShaderVariables.cginc(包含很多global variable)會自動加入,不用自己include。
UnityCG.cginc則有很多常用function,需要手動include。其他的文件多是在寫surface shader時會用到。

UnityCG.cginc中預先定義的struct

library文件列表(部分列出):https://docs.unity3d.com/Manual/SL-BuiltinIncludes.html

常用的struct:
appdata_base:vertex POSITION、normal NORMAL、texcoord TEXCOORD0
appdata_tan:vertex POSITION、tangent TANGENT、normal NORMAL、texcoord TEXCOORD0
appdata_full:vertex POSITION、tangent TANGENT、normal NORMAL、texcoord TEXCOORD0、texcoord1-3 TEXCOORD1-3、color COLOR
appdata_img:vertex POSITION、texcoord TEXCOORD0
v2f_img:pos SV_POSITION、uv TEXCOORD0

我自己寫Shader時一般不會用這些預先定義好的struct,因為不能讓人一看就知道這些struct中包含哪些semantics,有時候你想賦予的semantics名稱和它不一樣,要增加或減少semantics時也會麻煩,最好還是自己親自寫好每個semantics並命名。不過這些預先定義好的struct在library裡原始碼倒是會經常用到,所以如果你會經常查看library原始碼的話就要好好了解這些struct代表哪些semantics。

跨平台問題

一些常見的平台之間的差異:https://docs.unity3d.com/Manual/SL-PlatformDifferences.html