UE4地圖的性能優(yōu)化
(搬運其他人的文章)用于自己記錄知識點
文章一共分為ABC,依次深度優(yōu)化
A簡單的優(yōu)化方向:(美術(shù)向)
1:給模型設(shè)置LOD(Levels Of Detail)
LOD是Levels Of Detail的縮寫,直譯為細節(jié)的等級,lod可以讓模型的面數(shù)or頂點數(shù)根據(jù)攝像機的距離發(fā)生變化,離得越遠,模型的面數(shù)越低,細節(jié)等級就越低,想必大家都玩過吃雞,跳傘時遠處的房子就像一坨奧利給,但是落地之后就變的精細了,這就是lod的功效。

所以使用了LOD之后可以極大節(jié)省CPU和GPU的性能開銷,能夠大幅提升幀率。
LOD的設(shè)置方法
1:打開你的模型(我這里用個長凳做示例)

2:右邊細節(jié)面板找到lod設(shè)置

LOD導(dǎo)入:導(dǎo)入自己制作的lod模型
最小lod:模型顯示的最小lod等級
流送的lod數(shù)量:最大可以顯示多少個lod,如果值為-1,則是無限
Lod數(shù)量:模型擁有的lod數(shù)量(lod數(shù)量越多,細節(jié)過渡越平滑)
自動計算lod距離:由ue4自動計算lod精細度(建議關(guān)閉)
3:簡化設(shè)置
在我們設(shè)置完lod之后,在lod選取器里打開lod的自定義選項

打開自定義,可以設(shè)置每個lod層級的屬性

屏幕尺寸:數(shù)值越小,說明模型離攝像機越遠
三角形百分比:百分比越接近100%模型的面數(shù)就越多,反之越接近0%,模型面數(shù)越低
注:LOD0是細節(jié)程度最高的一個層級,LOD1則次之,往后以此類推




2:紋理流送(TextureStreaming)
紋理流送,也就是MipMap,根據(jù)貼圖與攝像機距離自動計算貼圖的分辨率,其算法是每一級別的分辨率是上一級別的四分之一,這里拿自♂由男人的照片舉個例子

經(jīng)歷了紋理流送的貼圖就會變成下面這樣

這也就使遠距離的貼圖分辨率降低,從而減少顯存的占用,ue4的紋理流送正常是自動開啟的,如果你要做高精度影視級別的工程的話,可以在項目設(shè)置里關(guān)閉紋理流送

除了ue4自動計算的紋理流送,我們也可以自己更改紋理流送的距離值
1:選中一個紋理資源

2:mip值模式改成“mip偏差(相對計算的mip等級)”

3:新建一個常量,連接到紋理資源的Bias接口上

4:把材質(zhì)轉(zhuǎn)化成材質(zhì)示例,這樣我們就可以實時調(diào)整這個常量的值了
5:這個常量的值越小,流送的mipmap細節(jié)等級越高,值越大,流送的mipmap等級越低
3:構(gòu)建光照(最有效的方法)
一說到構(gòu)建光照啊,這電腦就開始瑟瑟發(fā)抖了,當然構(gòu)建光照也不是什么壞事,但是有很多ue4新手為了去掉經(jīng)常在屏幕上顯示的紅色字條,就一口氣把所有的光源改成動態(tài)光源了。

但是其代價可想而知,小場景還好說,大場景的幀數(shù)直接拉胯。但是有一點需要知道,為什么要構(gòu)建光照?
由于當前世代的機能限制和技術(shù)限制,我們的設(shè)備不能夠進行實時的計算GI漫射(全局光照漫反射),所以引擎的設(shè)計者有了一個非常妙的設(shè)計,讓引擎提前計算好漫反射之后的光照信息,再把信息轉(zhuǎn)化成一張陰影貼圖,包裹在模型上面,使場景的光照效果看起來非常好看,同時性能也會大幅提升。
這里對比下構(gòu)建光照后的視覺效果


這效果對比,顯而易見,構(gòu)建光照不僅能減少性能開銷,還能大幅提升視覺效果
在我之前的一個工程中,構(gòu)建光照之前最高畫質(zhì)測試1080p頂多能跑到50-60幀,但是使用固定光源并且構(gòu)建光照之后,竟然能夠跑到100幀!可以看來構(gòu)建光照確實是個好東西
4:給一點小提示
1:盡量少用半透明材質(zhì),半透明材質(zhì)的著色器開銷是最大的,所以趕緊減少場景里的玻璃吧
2:多使用反射捕捉盒子,其效果可出乎意料哦
3:模型面數(shù)盡量控制在合理范圍內(nèi),人物角色面數(shù)一般為6w以下,中小型物體一般為2w以下,大型建筑10w以下
4:遠景模型配合指數(shù)級高度霧搭配使用,就算玩家有8倍鏡他也看不清遠景
5:沒必要的模型就別給碰撞,CPU多余開銷?
B.優(yōu)化貼圖的性能開銷(TA技術(shù)美術(shù)向)
UE4貼圖與材質(zhì)優(yōu)化
本文主要是從優(yōu)化角度去提供一些貼圖和shader制作的思路,主要有基礎(chǔ)貼圖、蒙版貼圖與shader、圖集、HDR貼圖等。
一、基礎(chǔ)貼圖
有時候,當我們更改母材質(zhì)的節(jié)點后,需要等待好幾分鐘去讓它編譯shader,這個時候我們可以查看一下母材質(zhì)里用到的貼圖是不是基礎(chǔ)貼圖。所謂基礎(chǔ)貼圖,就是一組分辨率較小,用作母材質(zhì)參數(shù)的貼圖。

用作底色或者某些通道的T_Black、T_White、TGray,用作法線的T_BaseNormal等。我們只要導(dǎo)入幾張很小型的貼圖,在創(chuàng)建母材質(zhì)時用這些貼圖作為參數(shù),然后創(chuàng)建材質(zhì)實例賦予真正使用的貼圖。一方面可以加快母材質(zhì)的編譯速度,另一方面減少貼圖置換及貼圖優(yōu)化的成本(因為材質(zhì)實例的引用比母材質(zhì)的引用更安全)。
二、蒙版貼圖與shader
如果需要實現(xiàn)一個rpg游戲的技能cd的UI,你會怎么實現(xiàn)呢?
一些人可能會在PS拉一個漸變

然后把貼圖導(dǎo)入引擎,寫這樣一個shader。

我們也可以這樣寫

這樣的好處是:節(jié)省了工作流并且得到了理論上分辨率超高的mask貼圖。
但其實考慮到可以手寫的蒙版不是特別多,所以做項目時可以權(quán)衡兩種方式。有些美術(shù)更愛好去使用自己收藏的mask,也完全OK。但如果你是一個新手,我建議培養(yǎng)少使用外部貼圖的方式。
三、圖集
在UI制作的過程中,對于一些類似且關(guān)聯(lián)性較強(比如在同一個UMG中)的圖片,建議放入同一圖集。比如

四、慎用HDR
有時候,尤其是對于特效工程師來說,一些效果更傾向用HDR貼圖實現(xiàn)(比如一些火的特效)。但我仍然建議,能用普通貼圖+參數(shù)實現(xiàn)的效果,盡量移除HDR貼圖。因為HDR貼圖的壓縮方式導(dǎo)致hdr貼圖會占用大量包體體積。

五、運算節(jié)點
材質(zhì)運算的一些節(jié)點比較耗費性能,盡量避免。典型的比如if節(jié)點(用lerp替代)、divide節(jié)點(用乘法替代)、開方節(jié)點。
當然,只需要做的時候有意識地去盡量避免即可,不需要把這條當成不可逾越的規(guī)定。尤其是一些嚴重影響可讀性的運算,比如除以2π,不要非寫成乘0.159。為了性能去顯著降低可讀性是不可取的,關(guān)于性能和可讀性的關(guān)系,可能日后會專門開一篇文章,這里先記住可讀性是很重要的就行。
C.瓶頸定位
就是要找到造成性能開銷的最大元兇,也就是確定優(yōu)化的基本方向,才能深入和落實到細節(jié)層面,進行后續(xù)的分析和優(yōu)化工作。
而要搞清楚開銷主要發(fā)生在哪個階段,不可避免地還是要對 Game, Draw, GPU 對應(yīng)的三類線程以及它們之間的關(guān)系有更詳細的認識
Game Thread, Draw Thread, GPU Thread 的關(guān)系
stat unit 顯示的數(shù)值,都是在 一幀之內(nèi) 的耗時,那么在這一幀期間,Game, Draw, GPU 這三者是如何先后執(zhí)行的,可以參照下圖加以理解

這幾個線程是并行運行的。
當游戲按照圖中的流程執(zhí)行時,
Game線程會計算所有的游戲邏輯,game線程計算的所有數(shù)據(jù)都會被儲存起來,并被Draw線程使用,它會算出不需要渲染的內(nèi)容(這些內(nèi)容不會顯示在屏幕上)。
完了之后GPU線程會在屏幕上實際渲染出最終的像素
如果 GPU Thread 率先完成了它的工作,而其他二者仍在工作中(e.g. 已經(jīng)繪制好了當前幀,但下一幀的數(shù)據(jù)還沒拿到),那么 GPU 就會等待 CPU 的指令而導(dǎo)致下一幀的畫面姍姍來遲;反之如果 GPU 耗時更嚴重,導(dǎo)致 CPU 輸送的數(shù)據(jù)沒有被及時處理,使得畫面沒能被及時渲染,同樣會導(dǎo)致卡頓
Game Thread 首先會對整個游戲世界進行邏輯層面的計算與模擬(e.g.Spawn 多少個新的 actor、每個 actor 在這一幀位于何處、角色移動、動畫狀態(tài)等等),所有這些信息會被輸送到 Draw Thread
Draw Thread(也叫 Rendering Thread) 會根據(jù)這些信息,剔除(Culling)掉不需要顯示的部分(e.g. 處于屏幕外的物體),接著創(chuàng)建一個列表,其中包含了渲染每個物體必備的關(guān)鍵信息(e.g. 如何被著色、映射哪些紋理等等),再將這個列表輸送給 GPU Thread
GPU Thread 在獲取了這個列表之后,會計算出每個像素最終需要如何被渲染在屏幕上,形成這一幀的畫面
綜上,對于每一幀來說,這三者的執(zhí)行順序依次為:Game Thread → Draw Thread → GPU Thread?
Notes
一幀的總耗時,取決于三者中開銷最嚴重、即耗時最長的線程
Game Thread 和 Draw Thread 在 CPU 上運行,GPU Thread 在 GPU 上運行

所有的東西 從游戲邏輯所有的Actor的位置,場景中所有物體的位置 動畫,實際動畫幀,物理效果,AI,一切與場景最終效果有關(guān)的計算,在進行處理時都會在Game線程中計算。
這步完成后,整個游戲世界就被計算完畢了。
引擎就會知道什么東西該干什么。
在下一步“Draw”線程他會過濾掉(剔除掉)所有不在相機范圍內(nèi)的卻還需要引擎去渲染的對象,然后創(chuàng)建一個列表(包含所有的對象Object,著色器Shaders,材質(zhì)Materials,紋理貼圖Textures和所有需要發(fā)送給GPU的數(shù)據(jù))。
然后GPU會處理這些數(shù)據(jù)(包括頂點Vertex,著色器Shaders,紋理Textures等各種數(shù)據(jù)),然后會在屏幕上繪制最終像素。
手游瓶頸
基于UE的手游客戶端的性能主要由這七大部分構(gòu)成:CPU邏輯,CPU渲染,圖形API(提交),GPU渲染,內(nèi)存,帶寬,加載時間。
這幾個基本元素又會合力衍生出一些新的性能指標,例如功耗(往往同gpu負載和帶寬緊密相關(guān))。
同時這七部分又構(gòu)成一個閉合的木桶,最長的一塊是主要瓶頸,并且瓶頸可以在這幾塊轉(zhuǎn)移流動。
作為開發(fā)者我們解決性能問題的步驟一般都是按照做性能剖析,解讀結(jié)果,定位問題,增加剖析代碼,優(yōu)化問題,重復(fù)剖析的迭代過程來執(zhí)行。
而高效準確詳細的對性能進行剖析得到結(jié)果是第一步,在任何引擎上,只要我們能做到在任意時刻準確的獲取想要的性能剖析結(jié)果,那么才會胸有成竹不會慌
優(yōu)化準備
在尋找性能優(yōu)化和找到運行瓶頸時,需要根據(jù)項目實際運行的平臺上測試,游戲的運行環(huán)境越接近目標硬件和目標平臺,結(jié)果越準確。
PC端游戲
當游戲在是PC端運行時,可在在編輯器中運行,并且需要準備一些環(huán)境,剔除一些因素的影響:
1、需要關(guān)閉垂直同步 (為確保引擎中最大的幀速沒有被限制先設(shè)置下幀率)

2、需要關(guān)閉平滑幀-將參數(shù)置為false?

3、需要關(guān)閉實時光照

4、需要在standalone 下運行
5、最小化Editor 作者:_jiejie_cj https://www.bilibili.com/read/cv16498653 出處:bilibili
手游
當運行在手機時,需要打包合適的版本并在實際的運行平臺上測試,以保證結(jié)果的準確性。
命令行查看性能瓶頸:

1. Show FPS 查看游戲幀率
60.00FPS 表示 刷新率(單位為Hz),就是每一秒屏幕刷新的幀數(shù),幀數(shù)越高,刷新的越多即越流暢
16.67ms 表示刷新一幀所需要的時間,時間約少,刷新越快,
1000ms(1s) /16.67ms = 59.98即FPS
2. Show Stats 拆分Fps
Frame: 表示刷新每幀所需要的時間。
(刷新時間是由多個線程同時工作的最長的那個線程決定的)
Game(CPU 游戲邏輯線程):處理游戲邏輯所耗費的時間
這一步完全不考慮渲染問題,表現(xiàn)的是整個游戲世界在一幀之內(nèi),只在邏輯層面處理所有的變化需要花多長時間——Compute Game Context
這是一個任意的CPU邏輯,它不與渲染直接關(guān)聯(lián)。如果該組很慢,通常的情況是程序員有需要修正的內(nèi)容,但是它可以是與美術(shù)相關(guān)的,比如:屏幕上有太多顆粒。內(nèi)置在CPU分析器中的Frontend工具可以用來研究CPU性能并且觀察正運行緩慢代碼。特定的、與復(fù)雜任務(wù)相關(guān)的游戲設(shè)置只能在CPU上執(zhí)行,像A.I.和Navigation的設(shè)置。
Draw(繪圖): 準備好所有必要的渲染所需的信息,并把它從 CPU 發(fā)送給 GPU 所耗費的時間
承接上一步,在游戲世界在邏輯層完成所有的計算和模擬后,收集渲染所需的信息,并剔除非必要信息,通知 GPU 進行畫面渲染—— What to Render
這是一個與GPU上渲染設(shè)置相關(guān)的CPU邏輯。它包括圖形API和繪圖調(diào)用的設(shè)置,或者如果渲染代碼已經(jīng)以非最佳的方式修正了,它就可能與渲染代碼相關(guān)。
GPU:接收到渲染所需信息之后,將像素最終的表現(xiàn)畫在屏幕上的耗時
GPU渲染幀花費多長時間。它包括:執(zhí)行圖形API調(diào)用、繪圖調(diào)用、著色器和后過程著色器的執(zhí)行、獲取紋理……這里的問題通常與資源相關(guān),它可能是場景中類似著色器這樣非常復(fù)雜的東西,或者場景中有許多不同的網(wǎng)格,結(jié)果就是每幀中發(fā)生太多的繪制調(diào)用。這可能會讓一個專業(yè)美工或程序員找到問題根源,但是通常情況下需要一些決策——為了達到預(yù)期性能,應(yīng)該做哪些權(quán)衡。這里能幫到您的最棒的工具是GPU分析器和著色器復(fù)雜性視圖,這些會在之后進行討論,同時下面還會討論“Advance”目錄中顯示的特定stats。
如果一幀花的時間跟邏輯線程的時間比較接近,那么瓶頸在邏輯線程,相反如果跟渲染線程的時間比較接近,那么瓶頸在渲染線程。如果兩個時間 都不接近,但跟GPU時間比較接近,那么瓶頸在顯卡上。圖中我們可以看到 GPU 是限制主因(三者最大的一個)。為了取得更少的 單幀 時間,在這個情形下必須先優(yōu)化 GPU 的負載。
Stat Unit/Stat UnitGraph?

這三個部分越接近Frame的時間,說明瓶頸就在哪部分
3.通過屏幕分辨率判斷?

表示為原來分辨率的10%
若游戲突然變快,則瓶頸出現(xiàn)在GPU,因為分辨率變低,GPU渲染量計算量變少,游戲加快。?
優(yōu)化方向
如果一幀花的時間跟邏輯線程的時間比較接近,那么瓶頸在邏輯線程,相反如果跟渲染線程的時間比較接近,那么瓶頸在渲染線程。如果兩個時間 都不接近,但跟GPU時間比較接近,那么瓶頸在顯卡上。
當然也可以使用一些第三方工具,比如intel vtume,、aqtime等,移動平臺上可以使用Apple Instruments、NVIDIA Tegra System Profiler、ARM DS-5等 。
主要從CPU 和 GPU 兩個方面考慮:?

CPU 優(yōu)化
一、Game Thread
Game Thread 造成的開銷,基本可以歸因于 C++ 和藍圖的邏輯處理,瓶頸常見于Tick 和代價昂貴的邏輯實現(xiàn)(Expensive Functionality)
1、Tick
① 大量物體同時 Tick 會嚴重影響 Game Thread 的耗時,因為Tick 是每一幀都會執(zhí)行,計算引擎中所有東西狀態(tài)的函數(shù)。
但事實是 藍圖 至少是GamePlay藍圖,它們很少需要每幀更新。
因為大部分游戲腳本都是基于事件的?;蛘卟灰欢ㄐ枰繋几拢m然也有例外的時候,但大部分情況下你不需要那么做。
要記住如果你的場景和世界中,有許多Actor的“Tick”函數(shù)在運行。那就會嚴重拖累游戲的流暢度。
② stat game:顯示 Tick 的耗時情況
它能查閱游戲邏輯在特定情況下的每幀更新耗時。
③ dumpticks:可將所有正在 tick 的 actor 打印到 log 中
它能列出正在更新的所有Actor,以及它們的總數(shù)。

如果非不得已要在Tick里面添加復(fù)雜的邏輯,請慎重斟酌,是否真的需要這么做。
下面列出幾個替代Tick的方案:?

1:Timeline?

2. Timer?

3. manual toggling of Actor Tick 手動切換Tick
手動禁用和開啟Tick,比如禁用那些距離玩家太遠的Actor,它們不在攝像機里,在你靠近他們的時候再重新啟用。
4. reducing the tick interval 增加Tick的時間間隔.(分幀處理)

5. Event drien systems(use dispatchers?。┦录?qū)動.?

材質(zhì)效果方面,假如是要做簡單的淡出效果或者動畫,也就是像素著色器實現(xiàn)這類效果,這是個很簡單的例子,是要經(jīng)過了開始的時間,算法就會完成剩下的工作,即再兩個值之間插值,你就完全不會用到CPU線程,這都在GPU上運行。對這類效果來說,運行速度會非常快。?



在游戲開發(fā)中,我們還會遇到大量的包含簡單循環(huán)移動邏輯的對象,所以如果是某些和游戲玩法關(guān)系不大的邏輯:例如一些和關(guān)卡美化有關(guān)的邏輯,一些讓場景更好看的邏輯,可以讓材質(zhì)實現(xiàn),把它們改用頂點著色器實現(xiàn)(vertex shader),甚至用原生代碼來賦予它們旋轉(zhuǎn)動畫。
C++的“RotatingMovementComponent”就是個很好的方法。它用于讓對象自旋,但假如你還想進一步榨取性能,你就可以用頂點著色器實現(xiàn)它。


性能消耗大的幾個函數(shù)
?



用這些函數(shù)的時候一定要多加謹慎。
如果真的要調(diào)用這個函數(shù),請在基于事件的邏輯中調(diào)用它,比如在游戲啟動時調(diào)用它?;蛘呔帉懩撤N基于事件的邏輯。在只有需要訪問數(shù)據(jù)的時候才調(diào)用這個函數(shù)。然后把數(shù)據(jù)全部存到數(shù)組中,請記住這些好習(xí)慣!
如果用到for loop,尤其是涉及多重循環(huán)時,記得要及時中斷循環(huán),這樣等你找到需要的對象后就不用運行其余的循環(huán)了。
SpawnActor實際上官方已經(jīng)優(yōu)化完善了許多,但是在生成Actor的時候還是會占用很多資源,因為這同樣需要占用當前平臺的IO接口。所以如果你在游戲中需要頻繁生成Actor,可以考慮把場景中的Actor保存在緩存池中,還有要注意如果你真的要在Tick函數(shù)中實現(xiàn)復(fù)雜算法的和運算請考慮使用原生代碼 或者說C++。?

也不需要把所有的功能都挪到C++里面,只需要把復(fù)雜代碼的那部分移過去,因為可能只需要把有復(fù)雜代碼的那部分移過去因為它們需要做各種復(fù)雜計算只把那部分移到C++然后把它作為函數(shù)公開給藍圖然后就可以了。

如果你制作的3D游戲會用到動畫藍圖,記得要使用Fast Path,基本上動畫藍圖中的這種閃電圖標越多就越好。

2、復(fù)雜邏輯
需要借助 Unreal Frontend Profiler / Unreal Insights 等工具對游戲邏輯中開銷較大的代碼進行定位
Unreal Frontend Profiler工具
Unreal Insights 工具
二、Draw Thread (Rendering Thread)
Draw Thread 的主要開銷來源于 Visibility Culling 和 Draw Call
1、Visibility Culling
Visibility Culling 會基于深度緩存(Depth Buffer) 信息,剔除位于相機的視錐體(Frustum)之外的物體和被遮擋住(Occluded)的物體,當游戲世界中可見的物體過多,剔除所需的計算量也將變大,導(dǎo)致耗時過長
stat initviews:顯示 Visibility Culling 的耗時情況,同時還能顯示當前場景中可見的 Static Mesh 的數(shù)量(Visible Static Mesh Elements)

2、Draw Call
一般理解:CPU 準備好一系列渲染所需的信息,通知 GPU 進行一次渲染的過程
stat SceneRendering 可查看 Mesh Draw Call 的數(shù)量
即便場景中模型面數(shù)多,只要合批機制完善,Draw Call 的數(shù)量也可以非常少
相比于面數(shù),Draw Call 對性能開銷的影響要大得多?

stat scenerendering命令 場景渲染
Draw調(diào)用對性能有很大的影響。每當渲染器完成時,它需要接收來自渲染線程的命令,這增加了開銷。在許多情況下,DrawCall比polycount有更大的影響。在來回調(diào)用時,每當渲染器需要發(fā)送命令,或者你增加了開銷它實際的影響polycount(多邊形數(shù)量)影響還大。?

你可以用RenderDoc來調(diào)試繪制調(diào)用.
那要如何減少DrawCall?
使用更少更大的模型,把不同模型不同對象合并成一個模型(MergeActors)。當然這也不是絕對這么做就好,例如這樣做程序就不好做刪減,例如玩家在高樓大廈門口,只是看一眼一樓,就要將整棟樓一起渲染,引擎沒法將模型拆分成多個部分,因為這是個完整的模型。這對光照貼圖很不利,如果你使用了靜態(tài)光照,你就需要更大的光照貼圖(larger lightmaps)以便顯示更多細節(jié)。這對碰撞計算很不利,相比拆分成多個小型模型。碰撞效果的精度會差一些。當然這對內(nèi)存也不利,要加載更大的資源,可能會導(dǎo)致卡頓。
瓶頸在邏輯線程
可以通過性能分析來確定,通過~打開控制臺里面輸入"stat startfile",讓它運行一會至少10s來獲取一個多幀的平均值。如果時長過長,那么生成的文件就會很大。通過stat stopfile來結(jié)束性能分析。一個后綴為ue4stats的文件會在工程的路徑下產(chǎn)生,如果是android的話會在你安裝的目錄下面生成 一個profile目錄。如果想要查看分析結(jié)果,必須把這個文件拷貝到pc上,可以使用adb pull {ue4stats 完整路徑} {pc 保存路徑}來拷貝文件到pc上。
這個時候你就可以使用UnrealFrontEnd(跟UE4Editor在同級目錄)來打開分析的結(jié)果,或者在UE4Edtior里面通過window-->Developper ToolsàSession Frontend,打開后切換到Profiler面板,通過load來打開ue4stats文件。?

當打開后你就可以自己來查看耗費時間的地方了

如果要查看卡頓,可以在時間線上查看高峰的地方,通過選擇Maximum而不是Average,這樣它就會顯示一些峰值,如下圖所示。

GPU分析
如果是在PC平臺上可以使用ProfileGPU命令或者使用快捷鍵Ctrl+Shift+,


可以看出影響GPU瓶頸最主要的是BasePass和PrePass ,
PrePass / Depth only pass: RenderPrePass / FDepthDrawingPolicy 。渲染遮擋物,對景深緩沖區(qū)僅輸出景深。該通道可以在多種模式下工作:禁用、僅遮蔽,或完全景深,具體取決于活動狀態(tài)的功能的需要。該通道通常的用途是初始化 Hierarchical Z 以降低 Base 通道的著色消耗(Base 通道的像素著色器消耗非常大)。
Base pass : RenderBasePass / TBasePassDrawingPolicy。渲染不透明和遮蓋的材質(zhì),向 GBuffer 輸出材質(zhì)屬性。光照圖貢獻和天空光照也會在此計算并加入場景顏色。
Lighting : 陰影圖將對各個光照渲染,光照貢獻會累加到場景顏色,并使用標準延遲和平鋪延遲著色。光照也會在透明光照體積中累加。
Fog : 霧和大氣在延遲通道中對不透明表面進行逐個像素計算。
Post Processing : 多種后期處理效果均通過 GBuffers 應(yīng)用。透明度將合成到場景中。
其中BasePass 0 =不透明網(wǎng)格。
BasePass 1 =用于Z深度的Alpha蒙版不透明網(wǎng)格。
BasePass Dynamic =動畫頂點,如Skeletal,GeoCache(Alembic)等。
幾個值得注意的數(shù)據(jù)項:
Base Pass
Deferred Decals
Lighting
SSR(環(huán)境反射)
Translucency(半透明)
Postprocessing(后期處理效果)
Particle(粒子)
當Base Pass很高,可以使用命令行打開Early Z Pass 可以降低 Base Pass 但同時會少量增加DRAW CALL
檢查影響GPU效率的內(nèi)容查看有無超標現(xiàn)象
比如分辨率、HMD SP、投影貼圖大小
1:basepass消耗高的話,就需要了解下哪些模型,貼圖,材質(zhì)開銷太大。 面數(shù)過高的模型就減面;半透明用的多的物件就斟酌下是否必要;材質(zhì)是GPU消耗過高的一大元兇,比較耗的材質(zhì)可以檢查下節(jié)點,關(guān)閉一些非必要的效果。材質(zhì)復(fù)雜程度在這里可以查看,越紅的越消耗,原則上減少使用點動畫和曲面細分等一些效果。
紅色:意味著性能消耗非常高 綠色:意味著性能消耗最低半透明:意味著增加性能消耗

可在材質(zhì)里查看著色器的說明數(shù)量盡可能減少?

另外,場景里擺放的模型如果不需要參與碰撞計算的話,最好關(guān)閉碰撞,減少運算消耗。

游戲運行時在控制臺里使用showflag(隱藏)命令可以幫我們快速定位具體是模型?特效?光照?等等哪個消耗高,消耗高的就優(yōu)化,列舉幾個常用的”showflag.”命令“0”關(guān)閉“1”打開:
ScreenSpaceReflections: 切換屏幕空間的反射效果,可能會非常影響性能,對那些達到一定粗造度的像素有效
AmbientOcclusion: 屏幕空間環(huán)境遮罩
AntiAliasing: 切換各種抗鋸齒(TemporalAA 和 FXAA,F(xiàn)XAA更快,但效果較差)
Bloom: 影響那些受到 lensflares 和 bloom 功能的畫面。
DeferredLighting: 切換所有延遲光照通道。
DirectionalLightsPointLightsSpotLights: 切換不同的光照類型(檢查光照類型影響性能時有用)
DynamicShadows: 切換所有的動態(tài)陰影(陰影貼圖的渲染,以及陰影的過濾和投影)
GlobalIllumination: 切換預(yù)烘培和動態(tài)間接光照(LPV)
LightFunctions: 切換光照函數(shù)渲染
PostProcessing: 切換所有后處理效果
ReflectionEnvironment: 切換環(huán)境反射效果
Refraction: 切換折射效果
Rendering: 切換整體渲染
Decals: 切換貼花渲染
LandscapeBrushes StaticMeshesSkeletalMeshes Landscape: 輪詢切換幾種不同的幾何體的渲染
Translucency: 切換透明度渲染
Tessellation:切換曲面細分(仍將運行曲面細分 shader,但生成更多三角面)
IndirectLightingCache: 切換是否動態(tài)物體或者靜態(tài)物體具有使用間接光照 Cache 時無效的光照貼圖。
Bounds : 顯示編輯器中當前選中物體的邊界框。
VisualizeSSR :屏幕空間反射像素顯示為亮橙色是計算較慢的區(qū)域
關(guān)閉stuff查看效率
r.SetRes: 調(diào)整渲染分辨率
r.VSync 開啟/關(guān)閉垂直同步(可能依賴于是否原生全屏)。
r.AllowOcclusionQueries 用于禁用遮擋(可以讓場景運行的更慢)。
r.TiledDeferredShading 能夠關(guān)閉基于 Tile 的延遲光照技術(shù)(GPU粒子的光影則沒有退回方法)
.TiledDeferredShading.MinimumCount 能夠調(diào)整使用多少燈光應(yīng)用在基于 Tile 的延遲光照技術(shù)(視覺上并沒有差異但性能會有不同)
r.SeparateTranslucency 這是一個用于修復(fù)半透明情況下景深的問題的功能,如果不需要的時候可以把它關(guān)閉,并有其他影響(查閱 SceneColor)。
r.TonemApper.GrainQuantization 用于關(guān)閉在 TonemApper 中添加的噪點來避免 Color Banding,由于 8bit 量化和較小的質(zhì)量改進在輸出為 10:10:10 并不必須。
r.SceneColorFormat 能夠選用不同的 SceneColor 格式(默認是 64bit 的最佳質(zhì)量,并支持屏幕空間子表面散射)。
FX.AllowGPUSorting 禁用粒子排序(在大量粒子的使用可以妥協(xié)使用)。
FX.FreezeParticleSimulation 禁止粒子的更新。
r.MaxQualityMode: 最高質(zhì)量
r.MipMapLODBias: Mipmap Bias
r.MobileContentScaleFactor: 畫面縮放比
r.ScreenPercentage: 用于減小內(nèi)部實際渲染分辨率,畫面會在重新放大
r.ShadowQuality: 移動端Stationaary燈光動態(tài)陰影質(zhì)量,調(diào)整其值查看幀速變化,以判斷瓶頸
r.Shadow.MaxResolution: 移動端Movable燈光動態(tài)陰影質(zhì)量,調(diào)整其值查看幀速變化,以判斷瓶頸
StatMemory:提供關(guān)卡中內(nèi)存使用情況
2:燈光消耗高的話,需要檢查動態(tài)光照數(shù)量(固定光也可以投射動態(tài)光照),是否有過多重疊的照射區(qū)域,照射范圍參數(shù)是否開的太大。由于靜態(tài)光照Build后已將燈光信息存儲進了Lightmap,游戲中不再計算,所以燈光的主要消耗來自動態(tài)光源。先在世界大綱里查看所有燈光類型,確定有幾盞動態(tài)光和固定光,前面有紅點的是動態(tài),黃點的是固定。

再進一步查看固定光的照射范圍的重疊部分是否太多,重疊的越多,交集處越亮越紅。用燈的原則是能不用動態(tài)光就不用(消耗主要來自被投照射的Mesh),燈光照射范圍盡量不重疊,且同一個地圖里固定光不能超過4盞。
光照復(fù)雜度視圖模式基于動態(tài)光源的數(shù)量來對場景進行著色。
黑色:意味著沒有收到動態(tài)光源影響。
不同顏色:從綠到紅,表示受到動態(tài)光源的影響逐步增加。

關(guān)閉燈光的投射動態(tài)陰影也可以降低一些消耗,甚至一些燈光可以直接關(guān)閉投射陰影功能。


3:后期處理是另一個GPU消耗過高的元兇,需要慎用,原則是盡可能的把一些不必要的參數(shù)關(guān)掉,尤其是SSR,后期AO,Bloom等。一些參數(shù)默認會自帶一些數(shù)值,沒必要的全部清零,抗鋸齒模式切換成FXAA。
使用Alt+0/Light Map Density可以對場景中的光照貼圖密度進行分析。
其他數(shù)據(jù)分析
ShadowDepths
這個生成通過光源進行陰影投射的深度數(shù)據(jù)的pass。
作用與這里的消耗主要受到開啟了投影的光的數(shù)目、動態(tài)光照影響的面數(shù)、以及陰影的質(zhì)量的影響。
陰影的質(zhì)量可以通過Sg.shadow quality進行全局的調(diào)節(jié)。
Memory-bound
如果有大量的材質(zhì)使用了不同的貼圖,導(dǎo)致Texture Sample的數(shù)量爆炸的話,就會自然的變成瓶頸。UE4有使用Texture Streaming,如果存儲空間爆炸了的話,就會出現(xiàn)貼圖模糊的情況,這時候可以使用Stat Streaming指令進行分析。
PrePass DOM_…
EarlyZPass,對非透明物體進行的早期的深度計算。

數(shù)據(jù)似乎被用于遮蔽計算,如果不使用Dbuffer Decals的話可以關(guān)掉。但是早期的深度計算可以在BasePass之前進行遮蔽計算,能讓basepass以及之后所有的通道的計算減少很多。而且即便在這里不進行深度計算,會影響這里的運算量的變量依然會作用與后面的深度計算階段,因此關(guān)閉EarlyZPass還是需要多做考慮的。另外要使用DBuffer Decals的話必須使用Opaque and masked的zpass計算,否則應(yīng)該會出現(xiàn)奇怪的現(xiàn)象。?

性能上受到非透明物體的面數(shù)的影響,同時根據(jù)上面的選項不同也受到Masked的材質(zhì)的影響。
HZB
Hierarchical Z-Buffer,用于計算HZB遮蔽,同時也會被屏幕空間內(nèi)的射線演算使用,例如屏幕空間反射計算、AO等。同時被用于Mip的設(shè)置。受屏幕空間的大小影響。據(jù)官方描述,HZB擁有較高的固定性能消耗,每個物體所造成的消耗較小??梢酝ㄟ^r.HZBOcclusion來調(diào)整運算的類型。
Base Pass
對非透明的物體進行演算并填充到GBuffer,使用緩沖區(qū)可視化模式可以在視圖中看到效果。幾乎所有的延遲渲染都受到其影響,因此才叫基礎(chǔ)通道。
其計算結(jié)果包括base color, metallic, specular, roughness, normal, sss profile,并且Decals、Fog以及Velocity的計算也在此處。其開銷受到屏幕空間尺寸、物體數(shù)量、面數(shù)、Decals的數(shù)量、Shader的復(fù)雜度,生成的過程中包含光照貼圖的推送,因此也會受到光照貼圖的大小的影響??梢酝ㄟ^Stat rhi指令檢查各種貼圖和triangle的消耗。
另外,前向渲染的光照也在這里進行,此時光照的數(shù)量也會影響到這里的消耗。
Translucency
半透明的材質(zhì)以及光照演算,通過Stat gpu中的Translucency and Translucent Lighting可以進一步查看。消耗受到屏幕空間大小以及屏幕內(nèi)的半透明物體的數(shù)量影響,半透明物體的光照計算要盡量減少過度繪制。以及避免過多的需要進行半透明光照計算的光的數(shù)量。
Particle Simulation/Injection
粒子模擬,這里只展示GPU粒子的消耗,性能主要受粒子數(shù)量以及是否開啟了基于深度的粒子碰撞影響。粒子的優(yōu)化主要通過LOD以及設(shè)計上的優(yōu)化進行。
Post process
UE4的后期處理功能比較多,AA、DOF、自動曝光以及很多其他的功能都在其中。每種PP特效都會產(chǎn)生額外的性能消耗,如果使用了PP材質(zhì)的話,其復(fù)雜度也會影響性能。
Relection Envirionment
反射捕捉控件的計算緩存可以將顯示模式調(diào)整為Reflections來查看各個控件對緩存的影響通常的建議是,放一個大范圍的低精度反射捕捉,然后在需要的地方盡量不重疊的放置高精度的捕捉控件。影響性能的主要就是捕捉控件的數(shù)量及范圍,也受屏幕空間的大小影響。
Render Velocities
速度主要用于TAA以及Motion Blur,受到移動物體的數(shù)量以及其面數(shù)的影響。主要的優(yōu)化策略是使用LOD。
Screen Space Reflections
屏幕空間反射通過以下連個指令來進行調(diào)節(jié):
r.ssr.maxroughness 0.0-1.0
r.ssr.quality 0..4其中Maximum roughness決定著計算的范圍的大小。
也可以使用一些第三方工具來測試,pc平臺上如 Intel GPA、Nvidia NSight visual Studio edition,移動平臺比如高通的adreno profiler、NVIDIA Tegra Graphics Debugger、ImgTec PVRTune and PVRTrace、ARM Mali Graphics Debugger等,蘋果的XCode等均可以用來分析。
一些常用的命令

stat scenerendering




ViewMode ShaderComplexity
Stat UnitGraph完整的stat命令參考https://docs.unrealengine.com/latest/CHN/Engine/Performance/StatCommands/index.html。
幾個對分析最有用的變量:
r.SetRes 改變屏幕,或窗口的分辨率。
r.VSync 開啟/關(guān)閉垂直同步(可能依賴于是否原生全屏)。
r.ScreenPercentage 用于減小內(nèi)部實際渲染分辨率,畫面會在重新放大。
r.AllowOcclusionQueries 用于禁用遮擋(可以讓場景運行的更慢)。
r.TiledDeferredShading 能夠關(guān)閉基于 Tile 的延遲光照技術(shù)(GPU粒子的光影則沒有退回方法)。
r.TiledDeferredShading.MinimumCount 能夠調(diào)整使用多少燈光應(yīng)用在基于 Tile 的延遲光照技術(shù)(視覺上并沒有差異但性能會有不同)。
Pause 暫停游戲或者 Matinee(分析時更加穩(wěn)定,但禁用了 Update/Tick)。
Slomo 能夠?qū)τ螒蜻M行加速或者減速播放。
r.VisualizeOccludedPrimitives 顯示被裁剪掉的物件的外盒框。
StartFPSChart StopFPSChart 請看下文。
r.SeparateTranslucency 這是一個用于修復(fù)半透明情況下景深的問題的功能,如果不需要的時候可以把它關(guān)閉,并有其他影響(查閱 SceneColor)。
r.TonemApper.GrainQuantization 用于關(guān)閉在 TonemApper 中添加的噪點來避免 Color Banding,由于 8bit 量化和較小的質(zhì)量改進在輸出為 10:10:10 并不必須。
r.SceneColorFormat 能夠選用不同的 SceneColor 格式(默認是 64bit 的最佳質(zhì)量,并支持屏幕空間子表面散射)。
FX.AllowGPUSorting 禁用粒子排序(在大量粒子的使用可以妥協(xié)使用)。
FX.FreezeParticleSimulation 禁止粒子的更新。
r.SSR.MaxRoughness 調(diào)整屏幕空間反射(SSR)粗造度的最大值,并覆蓋后處理中的該設(shè)置。請查閱 Show Flag VisualizeSSR。
命令行選項
有些功能可以在命令行中進行關(guān)閉,比如 UE4.exe –NoSound
幾個對分析比較有用的開關(guān)是:
-NoSound 禁用聲音和音樂系統(tǒng)。
-NoTextureStreaming
關(guān)閉貼圖 steaming(對于隔離問題時很有幫助)。
-NoVerifyGC 否則需要預(yù)期在 Release 版本中每 30 秒會遇到的性能波動。
-NoVSync 能夠更快的渲染但會導(dǎo)致畫面撕裂,尤其是在高幀數(shù)下。
-Streaming 在使用 StartFPSChart/StopFPSChart 很有用,能夠從一個非 windows 設(shè)備上來獲取數(shù)據(jù)并用于進一步檢測(假設(shè)我們是實時的 cook 數(shù)據(jù))。
GPU 優(yōu)化
一、GPU Thread
1、頂點處理(Vertex-bound) 導(dǎo)致的瓶頸
①:Dynamic Shadow
目前動態(tài)陰影(Dynamic Shadow)的生成主要依賴 Shadow MApping,一種在光柵化階段計算陰影的技術(shù),Shadow MApping 每生成一次陰影需要進行兩次光柵化,因此當頂點數(shù)過多(可能源于多邊形數(shù)量巨大,也可能源于不適當?shù)那婕毞? 時,Dynamic Shadow 將成為 GPU 在光柵化階段的一大性能瓶頸
ShowFlag.DynamicShadows 0: 使用該指令可關(guān)閉場景內(nèi)的動態(tài)陰影(0表示關(guān)閉,1表示開啟),可在開啟和關(guān)閉兩種狀態(tài)間反復(fù)切換,查看卡頓情況是否發(fā)生明顯變化,以此判斷 Dynamic Shadow 是否確實造成了巨大開銷
2、著色(Pixel-bound) 導(dǎo)致的瓶頸
運行指令 r.ScreenPercentage 50,表示將渲染的像素數(shù)量減半(也可替換成其他 0-100 之間的數(shù)),觀察卡頓現(xiàn)象是否明顯減緩,以此判斷瓶頸是否 Pixel-bound
①:Shader Complexity
顯示對每一個像素所執(zhí)行的著色指令數(shù)量,數(shù)量越多,消耗越大
場景中存在過多的半透明物體(Translucent Object),會顯著增加 Pixel Shader 的計算壓力,使用 stat SceneRendering 可查看 Translucency 的消耗情況;使用 ShowFlag.Translucency 0 來關(guān)閉(0表示關(guān)閉,1表示開啟)所有半透明效果
當著色器(材質(zhì)連線)的實現(xiàn)邏輯過于復(fù)雜或低效時,也會導(dǎo)致較高的 Shader Complexity
在 Viewport 中選擇 Optimization Viewmodes → Shader Complexity,可視化 Shader 造成的開銷?

3、Quad Overdraw 重復(fù)渲染繪制
著色期間 GPU 的大部分操作不是基于單個像素,而是一塊一塊地繪制,這個塊就叫 Quad,是由 4 個像素 (2 × 2) 組成的像素塊
當模型存在較多狹長、細小的三角形時,有效面積較小,但可能占用了很多 Quad,Quad 被多次重復(fù)繪制,會導(dǎo)致大量像素參與到無意義的計算中,引起不必要的性能開銷

進入 Optimization Viewmodes → Quad Overdraw,顯示 GPU 對每個 Quad 的繪制次數(shù)

4、Light Complexity 關(guān)照重復(fù)
場景內(nèi)的動態(tài)光源(Dynamic Lights) 數(shù)量過多時,會產(chǎn)生大量動態(tài)陰影(Dynamic Shadow),如上述所說,容易引起較大開銷
動態(tài)光源的半徑過大,導(dǎo)致多個光源的范圍出現(xiàn)大量交疊,也可能導(dǎo)致嚴重的 Overdraw 問題
進入 Optimization Viewmodes → Light Complexity,查看燈光引起的性能開銷?

5、內(nèi)存(Memory-bound)引起的瓶頸
有時性能瓶頸還在于過高的內(nèi)存占用,其中最常見的是大量的紋理(Texture)加載和采樣
使用 stat streaming overview,查看當前紋理對內(nèi)存的占用情況
對于紋理的優(yōu)化,后續(xù)將另開新篇加以詳細介紹?

性能優(yōu)化實踐
https://blog.csdn.net/hechao3225/article/details/113742336
個人總結(jié):
美術(shù)方面優(yōu)化:
模型面數(shù)控制(進行LOD切換)
ID數(shù)量控制(進行材質(zhì)球合圖減少兆扣)
貼圖大小控制(統(tǒng)一貼圖大小,不能超過512*512)
遮擋體的制作(剔除看不到的物體)
裁剪機制(遠處物體直接裁剪掉不讓他出現(xiàn)在屏幕上以減少性能開銷)可以用霧氣遮擋
減少透明玻璃材質(zhì)/透貼等