(1)? ?用step()代替if else等條件語(yǔ)句:(edge=step(edge,_Edge);表示if(edge<=_Edge) edge=1 , else edge=0)
在片段著色器中将硝,以正常CPU編程的邏輯進(jìn)行優(yōu)化恭朗,例如,if(edge < _EdgeColor){return _EdgeColor;},如果此像素被判定為邊緣依疼,則直接返回邊緣顏色痰腮,那么則不用再進(jìn)行之后的運(yùn)算了。但這種優(yōu)化對(duì)于GPU編程來(lái)講是無(wú)效的律罢。再片段著色器中膀值,每個(gè)片段著色器每條指令操作上百個(gè)像素,如果有些片段采取一個(gè)分支而有些片段不采用另一個(gè)分支误辑,則所有片段都會(huì)執(zhí)行兩個(gè)分支沧踏,但只在每個(gè)片段應(yīng)該采取的分之上寫入寄存器。另外巾钉,if/endif等流程控制操作有較高的開銷(4個(gè)時(shí)鐘周期翘狱,Gefirce6系列(Nvidia))。因此在GPU編程中砰苍,ifelse,switchcase等條件語(yǔ)句和太復(fù)雜的邏輯是不推薦的潦匈。相應(yīng)的可以用階梯函數(shù)step()等函數(shù)進(jìn)行替換,這樣所有的線程都執(zhí)行完全一樣的代碼师骗。
(2)Shader資源解析優(yōu)化。一般來(lái)說(shuō)讨惩,一個(gè)Shader資源的物理Size僅幾KB辟癌,在內(nèi)存中也不過(guò)幾十KB。所以荐捻,Shader資源的效率加載瓶頸并不在其自身大小的加載上黍少,而是在Shader內(nèi)容的解析上。一般情況下处面,Shader加載的CPU耗時(shí)與其Keyword數(shù)量有關(guān)厂置,Keyword數(shù)量越多,則加載開銷也越大魂角。Shader的Keyword數(shù)量是會(huì)隨著場(chǎng)景設(shè)置的不同而變化的昵济。(注意:在Unity 5.x中,Unity默認(rèn)會(huì)根據(jù)場(chǎng)景設(shè)置野揪、Shader
Pass等來(lái)調(diào)整Shader的Keyword访忿,比如如果存在Lightmap的使用,則會(huì)默認(rèn)將對(duì)應(yīng)的Keyword打開斯稳,而對(duì)于沒(méi)有使用Fog的項(xiàng)目海铆,則會(huì)直接將相關(guān)Keyword關(guān)閉。)減少Keyword可以嘗試以下方法:
①盡量減少shader_feature和#pragma multi_compile等關(guān)鍵字挣惰,減小解析耗時(shí)卧斟,同時(shí)減少shader varaints(shader變體)數(shù)量殴边,從而減少內(nèi)存占用。
②通過(guò)skip_variants操作在Shader中直接去除相關(guān)Keyword,使用示例如下:
③直接去除Shader中的Fallback選項(xiàng)珍语。對(duì)于使用Mobile Shader的項(xiàng)目锤岸,可以嘗試直接將其Fallback去掉大幅降低keyword數(shù)量。
④使用AssetBundle方式加載資源廊酣,為避免大量相同的Shader被重復(fù)加載和卸載能耻,可采用以下加載方式:通過(guò)依賴關(guān)系打包,將項(xiàng)目中的所有Shader抽離并打成一個(gè)獨(dú)立的AssetBundle文件亡驰,其它AssetBundle與其建立依賴晓猛。Shader的AssetBundle文件在游戲啟動(dòng)后即進(jìn)行加載并常駐內(nèi)存,因?yàn)橐豢铐?xiàng)目的Shader種類數(shù)量一般在50~100不等凡辱,且每個(gè)均很小戒职,即便全部常駐內(nèi)存,其內(nèi)存總占用量也不會(huì)超過(guò)2MB透乾;后續(xù)Prefab加載和實(shí)例化后洪燥,Unity引擎會(huì)通過(guò)AssetBundle之間的依賴關(guān)系直接找到對(duì)應(yīng)的Shader資源進(jìn)行使用,而不會(huì)再進(jìn)行加載和解析操作乳乌。(注意:對(duì)于Unity4.x版本捧韵,Shader的AssetBundle加載后只需LoadAll即可完成所有Shader的加載和解析,但對(duì)于Unity5.x版本汉操,除執(zhí)行LoadAllAssets操作外再来,還需要進(jìn)行Shader.WarmupAllShaders操作(因?yàn)樵赨nity5.x版本中,Shader的解析和CreateGPUProgram操作是分離的)磷瘤,保證實(shí)際需要的Shader variants被完全加載芒篷,避免游戲過(guò)程中編譯Shader導(dǎo)致的hiccups(卡頓)。新的Unity版本中已由ShaderVariantCollection.WarmUp()代替Shader.WarmupAllShaders操作采缚。)