(三)unity中的渲染優化技術——————(節省帶寬、減少計算複雜度)

一、節省帶寬

大量使用未經壓縮的紋理以及使用過大的分辨率都會造成由於寬帶而引發的性能瓶頸。

1.1減少紋理大小

使用圖集可以幫助我們減少draw call數目,而這些紋理的大小同樣是一個需要考慮的問題,所有紋理的長寬比最好是正方形,而且長寬值最好是2的整數冪,這是因爲有很多優化策略只有在這種時候纔可以發揮最大效用,在unity5中,即便我們導入的紋理長寬值並不是2的整數冪,unity也會自動把長寬轉換到離他最近的2的整數冪值,但仍然要注意這個,防止由於放縮造成不好的影響。

除此以外還應該儘可能使用多級漸遠紋理技術(mipmapping)和紋理壓縮,在unity中我們可以通過紋理導入面板來查看紋理的各個導入屬性。通過把紋理類型設置爲Advanced,就可以自定義許多選項,例如是否生成多級漸遠紋理,如果勾選了,unity就會爲同一張紋理創建出很多不同大小的小紋理,構成一個紋理金字塔,在遊戲運行中就可以根據距離物體的遠近,來動態選擇使用哪一個紋理,這是因爲在距離物體很遠的時候,我們使用了非常精細的紋理,但肉眼也是分辨不出來的。這種時候,我們完全可以使用更小、更模糊的紋理來代替,這可以讓GPU使用分辨率更小的紋理,大量節省訪問的像素數目。在某些設備上,關閉mipmap往往會造成嚴重的性能問題,除非我們確定該紋理不會發生縮放,例如GUI和2D遊戲中使用的紋理等,都應該爲紋理生成相應的多級漸遠紋理。

紋理壓縮同樣可以節省帶寬,但是像Android這樣的平臺有很多不同架構的GPU,紋理壓縮變得有點複雜,因爲不同的GPU架構有它自己的紋理壓縮格式,例如PowerVRAM的PVRTC、Tegra的DXT格式、Adreno的ATC格式,所幸的是,unity可以根據不同的設備選擇不同的壓縮格式,而我們只需要把紋理壓縮格式設置爲自動壓縮即可。但是GUI類型的紋理同樣是個例外,一些時候由於對畫質的要求,我們不希望這些紋理進行壓縮。

1.2利用分辨率縮放

過高的屏幕分辨率也是造成性能下降的原因之一,尤其是對於很多低端手機,除了分辨率高其他硬件條件並不盡如人意,而這恰恰是遊戲性能的兩個瓶頸:過大的屏幕分辨率和糟糕的GPU。因此我們可能需要對於特定機器進行分辨率的放縮,當然可能會造成遊戲效果的下降,但性能和畫面之間永遠是個需要權衡的話題。在unity中設置屏幕分辨率可以直接調用Screen.SetResolution。

二、減少計算複雜度

計算複雜度同樣會影響遊戲的渲染性能,本節會介紹兩個方面的技術來減少計算複雜度。

2.1shader的LOD技術

shader的LOD技術可以控制使用的shader的等級,它的原理是,只有shader的LOD值小於某個設定的值,這個shader纔會被使用,而使用了那些超過設定值的shader的物體將不會被渲染。

我們通常在subshader中使用類似下面的語句來指明該shader的LOD值:

SubShader{
Tags{ "RenderType"="Opaque"  }
LOD 200
}

我們也可以在unity shader的導入面板上看到該shader使用的LOD值,在默認情況下,允許的LOD等級是無限大的,這意味着任何當前顯卡支持的shader都可以被使用,但是在某些情況下我們可能需要去掉一些使用了複雜計算的shader渲染,這時我們可以使用Shader.maximumLOD或Shader.globalMaximumLOD來設置允許的最大LOD值。

unity內置的shader使用了不同的LOD值,例如Diffuse的LOD爲200,而Bumped Specular的LOD爲400。

2.2代碼方面的優化

在實現遊戲效果時,我們可以選擇在哪裏進行某些特定的運算,通常來講遊戲需要計算的對象、頂點和像素的數目排序是對象數<頂點數<像素數。因此我們應該盡肯能把計算放在每個對象或逐頂點上,例如高斯模糊或邊緣檢測時,我們把採樣座標的計算放在了頂點着色器中,這樣的做法遠好於把它們放在片元着色器中。

在具體的代碼編寫上,不同的硬件甚至需要不同的處理。因此一些普遍的規則在某些硬件上可能並不成立,更不幸的是,通常shader代碼的優化並不那麼直觀,尤其是一些平臺上缺少相關的分析器,例如IOS平臺,儘管如此,本節還是會給出一些被認爲是普遍成立的優化策略,如果發現某些設備上性能反而有所下降的話,並不奇怪。

1.儘可能使用低精度浮點值進行運算,最高精度的float/highp適用於存儲諸如頂點座標等變量,但它的計算速度是最慢的,我們應該儘量避免在片元着色器中使用這種精度進行計算,而half/mediump適用於一些標量、紋理座標等變量,它的計算速度大約是float的兩倍。而fixed/lowp適用於絕大多數顏色變量和歸一化後的方向矢量,在進行一些對精度要求不高的計算時,我們應該儘量使用這種精度的變量它的計算速度大約是float的4倍,但要避免對這些低精度變量進行頻繁的swizzle操作(如color.xwxw)。還需要注意的是,我們應當儘量避免在不同精度之間的轉換,這有可能會造成一定的性能下降

2.對於絕大多數GPU來說,在使用插值寄存器把數據從頂點着色器傳遞給下一個階段時,我們應該使用盡可能少的插值變量,例如如果要對兩個紋理座標進行插值,我們通常會把它們打包在同一個float4類型的變量中,兩個紋理座標分別對應了xy分量和zw分量,對於PowerVR平臺來說,直接把不同紋理座標存儲在不同插值變量有時反而性能更好,這種插值變量是非常廉價的。

3.儘可能不要使用全屏後處理效果,如果美術風格實在需要使用類似bloom、熱擾動這樣的屏幕特效,我們應該儘量使用fixed/lowp進行低精度運算(紋理座標除外,可以使用half/mediump)。那麼高精度的運算可以使用查找表(LUT)或者轉移到頂點着色器中進行處理。除此之外,儘量把多個特效合併到一個shader中,例如我們可以把顏色校正和添加噪聲等屏幕特效在Bloom特效的最後一個Pass中進行合成。

還有一些其他代碼優化規則:

4.儘可能不要使用分支語句或循環語句。

5.儘可能避免使用類似sin、tan、pow、log等較爲複雜的數學運算,我們可以使用查找表來作爲替代。

6.儘可能不要使用discard操作,因爲這會影響硬件的某些優化。

2.3根據硬件條件進行縮放

諸如IOS和Android這樣的移動平臺,不同設備之間性能千差萬別,如何確保遊戲可以同時流暢地運行在不同性能的移動設備上呢?一個非常簡單的實用方式是使用所謂的放縮(scaling)思想,我們首先保證遊戲最基本的配置可以在所有的平臺上運行良好,而對於一些具有更高表現能力的設備,我們可以開啓一些更“養眼”的效果,比如使用更高的分辨率、開啓屏幕後處理特效、開啓粒子效果等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章