優化圖形性能
良好的性能對大部分游戲的成功具有決定作用。下面是一些簡單的指導,用來最大限度地提高游戲的圖形渲染。
圖形需要哪些開銷
游戲的圖形部分主要開銷來自電腦的兩個系統: GPU 或 CPU。優化的第一條原則是找到性能出現問題的地方;因為 GPU 和 CPU 的優化策略不盡相同(甚至可能截然不同 — 因此,通常在優化 CPU 的時候會給 GPU 帶來更多工作,反之亦然)。
主要瓶頸以及檢查瓶頸的方式:
GPU 通常受供給比率或內存帶寬的限制。
以更低的顯示分辨率運行游戲是否更快? 如果是,您極有可能受到了 GPU 上的攻擊比率限制。
CPU 通常受需要渲染的對象的數量限制,又稱“繪制調用”。
在渲染統計信息 (Rendering Statistics) 窗口中查看“繪制調用”,如果數值超過數千(電腦)或數百(手機),那么您可能需要優化對象數量。
當然,這些只是經驗法則;瓶頸也可能存在於其他地方。非主要瓶頸:
渲染不是問題,不管是對 GPU 還是 CPU!例如,您的腳本或物理可能是問題的根源。使用分析器找出問題所在。
GPU 需要處理的頂點過多。多少個頂點比較“適中”取決於 GPU 以及頂點着色器的復雜程度。對於手機來說,主要圖形“不應超過 10 萬個”,電腦則“不應超過 1000 萬個”。
CPU 要處理的頂點過多,因為這些對象要在 CPU 上進行頂點處理。這可能是蒙皮網格、棉布仿真、粒子等。
CPU 優化 — 繪制調用數量
為了渲染屏幕上的所有對象,CPU 任務艱巨 — 這些工作包括識別哪些光照效果會影響對象,設置着色器和着色器參數,向顯卡驅動發送調用命令,然后顯卡驅動准備將命令發送至顯卡。所有這些“逐對象” CPU 開銷都不小,因此,如果您擁有大量可見對象,它可以累計。
例如,如果您有 1000 個三角形,如果所有三角形都在一個網格內,而不是 1000 個獨立的網格分別擁有一個三角形,那么,成本將明顯降低。
這兩種情況在 GPU 的開銷非常類似,但是 CPU 渲染 1000 個對象(而不是一個)需要進行非常繁重的工作。
為了減少 CPU 的工作,最好減少可見對象的數量。
手動或使用 Unity 的繪制調用批處理將鄰近的對象組合在一起。
通過將獨立的紋理放在更大的紋理地圖集等操作,在對象中使用更少的材質。
盡量避免使用會導致對象多次渲染的效果(反光、陰影、逐像素光照等,如下所示)。
將對象組合起來,讓每個網格至少擁有數百個三角形,且每個網格僅使用一種材質 (Material)。組合兩個材質不同的對象不會給性能帶來任何的改善,理解這一點非常重要。擁有多種材質最常見的原因是兩個網格不共享相同的紋理,因此,如果要優化 CPU 性能,應該確保組合的所有對象共享同樣的紋理。
但是,在正向渲染路徑中使用大量像素光照時,有一些情況會使得合並物體不奏效,解釋如下。
GPU: 優化模型幾何體
在優化模型幾何體時,有兩條基本規則:
切勿使用過多的三角形
盡量降低 UV 貼圖接縫和硬邊緣的數目(頂點增加一倍)
請注意,圖形硬件處理頂點的實際數量通常和 3D 應用程序顯示的數量有所不同。建模應用程序通常顯示幾何頂點的數量,例如構建模型不同角點的數量。但是,對於圖形卡,將需要一些幾何頂點拆分成兩個或兩個以上的邏輯頂點來渲染。如果頂點有多個法線、UV 坐標或頂點顏色,則必須分割。因此,在 Unity 的頂點計數始終比 3D 應用程序計數高很多。
雖然模型中的幾何體的總數主要與 GPU 相關,Unity 的某些特性可以在 CPU 上處理模型,例如,網格蒙皮。
光照性能
完全不需要計算的光照始終是最快的!使用光照貼圖“烘焙”一次靜態光照,而不是逐幀計算。生成光照貼圖環境的過程僅比在 Unity 將光照直接放置在場景稍微長一點點,但是:
它的運行更快(2 種逐像素光照快 2-3 倍)
由於可以烘焙全局光照,且光照貼圖渲染器可以使渲染結果更光滑,因此,它的視覺效果更好。
在很多情況下,這是着色器和內容可以使用的簡單的技巧,而無需在場景中添加更多的光照。例如,您無需添加直接照射至相機的光照,取得“邊緣照明”效果,只需直接在着色器中添加專門的“邊緣照明”計算即可。
正向渲染光照
逐像素的動態照明將顯著增加每個受影響的像素的渲染開銷,並可能導致對象多次渲染。在硬件較弱的設備上,如手機或低端 PC GPU,應避免多於一個像素照明 (Pixel Light) 照亮任何單一物件,並盡量使用光照貼圖照亮靜態物體,而不是逐幀計算其光照。逐頂點的動態照明顯著增加頂點轉變的開銷。盡量避免多個燈照亮任何給定物體。
如果使用像素光照,那么,每個網格渲染的次數和被像素燈照亮的次數一樣。如果結合兩個距離較遠的網格,就將增加組合物體的有效大小。照亮這個組合物體的任何一部分的所有像素燈都會在渲染過程中計算,所需的渲染通道數量也會增加。一般而言,渲染組合物體的通道數量是每個單獨物體的通道數量之和,因此,組合不會有任何好處。出於這個原因,您不應組合距離較遠而不會同時受到不同像素燈影響的網格。
在渲染時,Unity 找到了網格周圍的所有燈光,並計算出哪些燈光對網格具有最大的影響。質量設置 (Quality Settings)用來修改最終成為像素光照的燈光數量,以及頂點光照的數量。每種燈光都會按照燈光與網格的距離,以及燈光的強度計算其重要性。此外,僅從游戲環境來看,某些燈光更為重要。因此,每種燈光都可以設置渲染模式 (Render Mode) 為重要 (Important) 或者不重要 (Not Important)。標記為不重要 (Not Important) 的光照通常具有較低的渲染開銷。
舉個例子,試想一下一款賽車游戲,玩家的汽車打開車頭燈在夜間行駛。車頭燈是游戲中最重要的光源。因此,它們的渲染模式 (Render Mode) 應設置為重要 (Important)。另一方面,在游戲中其他不那么重要的燈(如其他汽車的尾燈),即使成為像素燈也不會很大地提升游戲的視覺效果。此類燈光的渲染模式 (Render Mode) 可放心設置為不重要 (Not Important),避免在不能改善游戲的地方浪費渲染性能。
優化逐像素光照可同時節約 CPU 和 GPU: CPU 的繪制調用更少,GPU 要處理的頂點更少,且所有這些額外的對象渲染需要的點陣化像素更少。
GPU: 紋理壓縮和 Mipmaps
使用壓縮紋理 (Compressed Textures) 可以減少紋理的尺寸(使加載時間更快,內存占用更少),同時也可以顯著增強渲染性能。壓縮紋理僅使用未壓縮 32 位 RGBA 紋理所需的內存帶寬的一小部分。
使用 Mip Maps 紋理
根據經驗,三維場景中使用的紋理應始終啟用生成 Mip Maps (Generate Mip Maps)。在 GPU 渲染時,紋理壓縮可以以同樣的方式幫助限制紋理數據傳輸量,mip 貼圖的紋理讓 GPU 能讓較小的三角形使用較低分辨率的紋理。
此規則的唯一例外是當 texel(紋理像素)1:1 映射到渲染屏幕像素時,如 UI 元素或二維游戲中。
LOD 和每層消隱距離 (Per-Layer Cull Distances)
在一些unity3D游戲中,可能更多地要剔除小對象,以減少 CPU 和 GPU 負荷。例如,在足夠遠的距離內,大型建築物依然可見,而小石塊和碎片可以隱藏。
這可以通過細節層次系統或在相機上手動設置每一層的消隱距離實現。可以將更小的對象放在隔離層中,並使用Camera.layerCullDistances 腳本功能設置每層消隱距離。
實時陰影
實時陰影非常精美,但是它們可能消耗大量性能,不管是 CPU 的額外繪制調用,還是 GPU 的額外處理。更多詳細信息,請參閱陰影頁面。
GPU: 編寫高性能着色器的技巧
高端 PC GPU 和低端移動 GPU 的性能可能有天壤之別。就算單個平台同樣如此。在 PC,高速 GPU 的運行速度可能比遲鈍的集成 GPU 快幾十倍;在移動平台上,您也會發現 GPU 大有不同。
因此,請記住,移動平台和低端 PC 的 GPU 性能比您的開發機器要慢得多。一般來說,着色器需要手動優化,以減少計算和紋理讀取,獲得良好的性能。例如,一些內置 Unity 着色器的“手機”等價物更為快速(但是有一些限制或極限,這也正是其快速運行的原因)。
以下是一些指導,讓您了解哪些因素對於移動和低端 PC 顯卡最為重要:
復雜的數學運算
復雜的數學函數(如 pow,exp,log,cos,sin,tan 等等)會大大增加 GPU 負擔,所以一個好的經驗法則是,此類運算在每個像素中不得超過一個。考慮在合適時使用查找紋理作為替代選擇。
但是,我們不建議您編寫自己的 normalize,dot,inversesqrt 等運算。如果使用內置運算,驅動程序會為您生成更好的代碼。
請記住:alpha 測試(拋棄 (discard))運算會讓片段速度變慢。
浮點運算
編寫自定義的着色器時,應始終指定浮點變量精度。為獲得最佳性能,挑選精度盡可能小的浮點格式至關重要。很多台式機 GPU 均完全忽略運算精確,但是它對於大量移動 GPU 的性能具有重大影響。
如果着色器使用 Cg/HLSL 編寫,那么精度規定如下:
float — 完整的 32 位浮點格式,適合用於頂點變換,但性能最慢。
half — 簡化的 16 位浮點格式,適用於紋理 UV 坐標且比 float 大約快兩倍。
fixed — 10位定點格式,適合色彩、照明計算和其它高性能操作,速度大約比 float 快 4 倍
如果着色器以 GLSL ES 編寫,那么浮點精度將分別規定為 highp、mediump、lowp。
如需更多有關着色器性能的詳細信息,請參閱着色器性能頁面。
讓游戲速度更快的簡易檢查表
保持頂點數在 200K 以下,針對 PC 時每幀應為 3M,主要取決於目標 GPU。
若使用內置着色器,請在移動 (Mobile) 或未點亮 (Unlit) 的類別中選擇。它們對非移動平台同樣有效,但是是更復雜的着色器的簡化和限制版本。
每個場景中不同材質的數量盡可能少 — 不同對象之間盡可能共享相同的材質。
在非移動對象上設置靜態 (Static) 屬性,允許靜態批處理 (static batching) 等內部優化。
切勿在不必要的情況下使用像素燈 — 選擇只有一個(最好是方向光)像素燈的光線影響您的幾何圖形。
切勿在不必要的情況下使用動態光源 — 而應選擇烘焙照明。
可能的話使用壓縮紋理格式,否則使用 16 位紋理優於 32 位。
切勿在不必要的情況下使用霧效。
了解遮擋剔除的好處,在有大量遮擋的復雜靜態場景中,可以用它來減少可見幾何體的數量和繪制調用。計划您的關卡,以充分利用遮擋剔除。
使用天空盒制造“偽造”的遙遠幾何體。
使用像素着色器或紋理組合器混合多種紋理,而不使用多通道方法。
如果編寫自定義着色器,應始終使用最小的浮點格式:
fixed / lowp — 用於顏色、光照信息和法線,
half / mediump — 用於紋理 UV 坐標,
float / highp — 避免在像素着色器中計算頂點的位置,而應使用頂點着色器。
在像素着色器中盡量避免使用復雜數學運算,如 pow、sin、cos 等。
每個片段中使用較少的紋理。