Shader中的shader_feature與multi_compile

weixin_34320159發表於2017-07-02

問題是這樣的,我照著Unity5 的Standard shader寫了一個給我們工程用的簡化版的標準Shader以及配合使用的ShadergGUI,裡面融合了很多功能,包括支援法線啊、uv動畫啊、半透鏤空等等,通過shader_feature定義的巨集將這些效果融合到一個shader裡,這樣既方便了美術,也方便了shader的管理,不用像原來一樣工程裡亂七八糟的一堆shader了。

不過後期在真機測試的時候遇到了一個問題,就是我通過EnableKeyword來動態修改材質表現在裝置上不好使了。當時第一想法就是Shader中那麼多條件巨集在build的時候被Unity自動strip掉了,因為我們大部分的資源都打包成了Assetbundle包,工程實際只有一個空場景,Shader資源都放在了Resources目錄下。如果說因為build的場景和資源裡不包含shader的一些variant而被Unity自動去掉了這也是可以理解的。於是我就想GraphicsSettings裡不是有個Always Included Shaders麼,按照字面意思理解把shader放到那裡去總是可以了吧,於是我就按下圖設定了下。嘿!還真就好了! 

6718063-863a9382231e8182

既然這樣好了,那看來真機除錯時其他的一些問題比如角色表現增強效果應該也是這個原因嘍,那索性把其他的shader也都加進來吧,省的後面再出問題。別說這招真是包治百病,單機介面裡我們還用了不少Standar shader,也就新增進來吧。ok,一切問題解決。。。。。。了嗎? 
第二天測試就告訴我這個版本閃退頻繁,一查都是記憶體爆了。拿Instrument一看我靠,一登入就快300MB了,看下Allocation,編譯Shader居然就用了100多MB。難道說跟昨天把Standard Shader加進去導致的?雖然是很懷疑不過既然除錯已經定位到這裡還是試一下吧,於是乎把Standard shader從Always Included Shaders列表中移除再發布,嘿!還真就好了!

現在的情況就是 
1.真機執行時Shader.EnableKeyword不好使,應該是因為Unity在Build時自動把沒有用到的variant刪減掉了(不是結論) 
2.通過Always Included Shaders設定解決了問題,不過導致記憶體大量增加,應該是因為Unity在啟動時把該列表內的Shader的全部variant都展開編譯了出來,所以一方面解決了上面的問題,一方面卻增大了記憶體,而至於記憶體為什麼會增加如此之多,那隻能靠猜的了。 
既然這樣,那就要想辦法解決Shader的記憶體佔用了,既然全部variant佔據的空間太大就部分載入唄,正好Unity5增加了個ShaderVariantCollection這麼個東西,看看好不好用。結果。。。。。多天的各種實驗全部以失敗告終,這包括: 
1.建立ShaderVariantCollection資源,包含目標shader的全部variant,並新增到GraphicsSettings的Preload Shaders列表中 
2.通過程式碼建立ShaderVariantCollection,並呼叫WarmUp介面


下面總結下我分析出來的Unity5.0 - 5.2的Shader編譯載入策略 
1. 釋出工程時,Unity 會將全部multi_compile定義巨集組合成的variant編譯並加入包中 
2. 釋出工程時,Unity 會將全部關聯材質引用到的variant編譯並加入包中 
3. 釋出工程時,Unity會將Always Included Shaders列表中全部Shader的全部variant編譯並加入包中 
4. Build Assetbundle時,Unity會將關聯的Shader的全部由multi_compile定義的variant以及使用到的variant編譯並加入包中

實測,使用multi_compile,是可以在執行時(真機上)用EnableKeyword和DisableKeyword動態改變材質,而shader_feature不行

文件中也寫到:
So shader_feature makes most sense for keywords that will be set on the materials, while multi_compile for keywords that will be set from code globally.
shader_feature適合在材質中設定,而multi_compile 適合用程式碼全域性設定

相關文章