編寫shader時的一些建議:
1、只計算需要計算的東西;
2、通常,需要渲染的像素比頂點數多,而頂點數又比物體數多很多。所以如果可以,盡量將運算從PS移到VS,或直接通過script來設置某些固定值;
3、在使用Surface Shader時,可以通過一些指令讓shader優化很多。
通常情況下,Surface shader的很多默認選項都是開啟的,以適應大多數情況,但是很多時候,你可以關閉其中的一些選項,從而讓你的shader運行的更快:
(1) approxview 對於使用了view direction的shader,該選項會讓view dir的normalize操作per-vertex進行,而不是per-pixel。這個優化通常效果明顯。
(2) halfasview 可以讓Specular shader變得快一些,使用一個介於光照方向和觀察方向之間的half vector來代替真正的觀察方向viewDir來計算光照函數。
(3) noforwardadd Forward Render時,完全只支持一盞方向光的per-pixel渲染,其余的光照全部按照per-vertex或SH渲染。這樣可以確保shader在一個pass里渲染完成。
(4) noambient 禁掉ambient lighting和SH lighting,可以讓shader快一點兒。
4、浮點數精度相關:
float:最高精度,通常32位
half:中等精度,通常16位,-60000到60000,
fixed:最低精度,通常11位,-2.0到2.0,1/256的精度。
盡量使用低精度。對於color和unit length vectors,使用fixed,其他情況,根據取值范圍盡量使用half,實在不夠則使用float。
在移動平台,關鍵是在fragment shader中盡可能多的使用低精度數據。另外,對於多數移動GPU,在低精度和高精度之間轉換是非常耗的,在fixed上做swizzle操作也是很費事的。
5、Alpha Test
Alpha test和clip()函數,在不同平台有不同的性能開銷。
通常使用它來cull那些完全透明的像素。
但是,在ios和一些android上使用的PowerVR GPUs上面,alpha test非常的昂貴。
6、Color Mask
在移動設備上,Color Mask也是非常昂貴的,所以盡量別使用它,除非真的是需要。
shader多版本編譯:
shader variants(shader 變種)使用方式:
(1)#pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON
(2)#pragma shader_feature FANCY_STUFF_OFF FANCY_STUFF_ON
#pragma shader_feature FANCY_STUFF是#pragma shader_feature _ FANCY_STUFF的快捷方式,同樣會生成兩個變種
shader_feature和multi_compile的區別:
shader_feature:未使用的變種不會build進游戲;
multi_compile:會編譯生成所有變種。
用法:shader_feature更適用於材質的關鍵字,而multi_compile更適用於代碼設置的全局關鍵字。
關鍵字個數限制:
unity最多支持256個關鍵字,並且unity內部已經使用了60個左右。另外,可以在unity的工程設置中定義一些全局有效的關鍵字,這樣也會消耗一些數量,所以在編寫shader時要注意數量不要超過上限。
內置的multi_compile快捷組合:
#pragma multi_compile_fwdbase 編譯ForwardBase需要的所有關鍵字變種,包括不同的lightmap類型,主要的方向光是否開啟陰影等。
#pragma multi_compile_fwdadd 編譯ForwardAdd Pass包含的關鍵字變種。
#pragma multi_compile_fwdadd_fullshadows 和上一個類似,另外還包含了光照實施陰影的能力。
#pragma ulti_compile_fog 霧效。
上面內置的快捷方式包含了很多的變種,但可以通過skip_variants來屏蔽某些關鍵字:
#pragma skip_variants POINT POINT_COOKIE
硬件級別shader變種:
提供針對不同硬件(比如gles和gles 3.0)的shader變種。(針對硬件能力級別的優化)
#pragma hardware_tier_variants renderer
d3d11 - Direct3D 11/12
glcore - OpenGL 3.x/4.x
gles - OpenGL ES 2.0
gles3 - OpenGL ES 3.x
metal - iOS
/Mac Metal
vulkan - Vulkan
d3d11_9x - Direct3D 11 9.x feature level, as commonly used on WSA platforms
xboxone - Xbox One
ps4
- PlayStation 4
psp2 - PlayStation Vita
n3ds - Nintendo 3DS
wiiu - Nintendo Wii U
添加了上述#pragma的shader會自動生成三個關鍵字變種:
UNITY_HARDWARE_TIER1
UNITY_HARDWARE_TIER2
UNITY_HARDWARE_TIER3
編輯器模式下,可以在Graphics Emulation中來手動設置使用哪個變體。
上述三中變體,同時只會加載其中一種,
指定方式:
(1)自動檢測:在加載時,Unity檢測GPU並進行設置;如果檢測不到,默認選擇最高級。
(2)手動設置來制定使用哪一個tier,代碼如下:(一定是在shader加載之前制定,在某個shader加載之后再指定是不會影響該shader的)
Graphics.activeTier = UnityEngine.Rendering.GraphicsTier.Tier1;
平台shader設置:
可以通過代碼手動設置[平台, tier, 設置]
UnityEditor.Rendering.EditorGraphicsSettings.SetTierSettings(BuildTargetGroup target, GraphicsTier tier, TierSettings settings);

