您好,登錄后才能下訂單哦!
本篇內容介紹了“Render中關于Unity渲染優化的方法是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
首先,要明確一點:整個渲染工作只有當CPU和GPU完成了各自全部的任務時,才能成功渲染出一幀畫面。任意一個任務執行超時,都會導致整個這一幀的渲染延時。
渲染問題一般可分為兩類,第一種是由低效的渲染管線引起的。渲染工作中的一步或多步耗時過長,執行效率低下,打斷了平滑的數據流,便會導致低效的渲染管線,這種現象我們也稱之為 渲染瓶頸(bottlenecks)。第二種是由于一口氣向渲染管線發送過多的指令引起的渲染瓶頸。
當我們發現游戲里渲染一幀需要很長的時間,而且與CPU的執行效率有關,這種情況我們稱之為 CPU瓶頸(CPU bound)。同樣的,當我們發現游戲渲染一幀時間過長與GPU花費了大量的時間進行渲染計算有關,這種情況我們稱之為 GPU瓶頸(GPU bound)。
在對我們的代碼進行修改之前,通過合適的性能分析工具來定位渲染性能問題很重要,要對陣下藥,當然合理的對我們的修改進行評估也很重要。性能優化是一種權衡行為,可能對這方面性能的改善會給其他部分帶來負面影響。
Profiler窗口工具
Profiler 窗口 工具可以讓你實時監控游戲性能的表現。我們可以通過Profiler工具看到我們游戲中的許多方面,包括內存使用情況,渲染管線使用情況,以及用戶腳本使用情況(代碼質量)。
Frame Debugger
Frame Debugger 可以讓我們看到游戲每一幀是如何一步步渲染的。它可以讓我們看到更多的細節,包括每一個draw call它讓GPU渲染了哪些東西,它影響了shader代碼塊中的哪些屬性 以及 CPU 發送給GPU的事件,這些信息將幫助我們理解我們的游戲是如何渲染的,并且該如何改進我們的性能表現。
一般來說,CPU這部分工作與渲染相關的步驟如下:
決定要被渲染的對象
準備要發送給GPU的數據
發送指令給GPU
這些步驟由許多獨立的任務組成,而這些任務又多線程來處理。多線程可以同時處理多個任務。這意味著整個渲染工作可以更快。我們也稱這種工作模式為多線程渲染(multithreaded rendering)。
Unity的渲染進程主要由三種類型的線程來執行:主線程,渲染線程,工作線程。
主線程主要是處理CPU的大多數任務,包括部分渲染任務。
渲染線程顧名思義,專門是處理那些CPU發送給GPU的指令的任務。
工作線程中的每個線程各自都處理一個任務,比如一些剔除任務或材質蒙皮任務。
至于哪些任務由哪些線程來處理主要取決于我們在項目中的 設置(settings)以及我們項目運行的 硬件設備(hardware)。比如,內核越多的CPU,就擁有更多的工作線程。因此,同一款游戲在不同的設備可能表現截然不同。
由于多線程渲染是一項復雜且依賴硬件設備的工作,我們在優化方面就必須考慮是什么導致了我們的CPU瓶頸。如果問題是出在CPU花費了很多時間執行剔除工作這個線程上,那么你從CPU發送指令到GPU的這件事上進行優化也是于事無補的,因為它們不在同一個線程。
當然,也不是所有的平臺都支持多線程渲染,至少在寫這篇文章時,WebGL還不支持這個功能。如果一臺設備不支持多線程渲染,所有的CPU任務都將被同一個線程執行,這樣雖然在渲染效率上不如其他設備,但是一旦發生了CPU瓶頸,你的任何針對CPU方面的優化手段都會提升CPU的表現。
Graphics jobs選項
這個選項用戶可以通過打開player settings找到
它的功能是決定unity是否使用工作線程來處理渲染的任務,如果不勾選,則主要還是使用主線程或渲染線程。在支持graphics jobs的平臺上,勾選該選項,可以很大提升性能表現。大家可以自行測試觀察性能效果。
向GPU發送渲染指令
一幀向GPU發送過多的渲染指令,在 CPU瓶頸(CPU bound)中是最常見的問題,這個任務在大多數的平臺上都是發生在渲染線程上,但是某些平臺(如PS4等)是發生在工作線程上。
這類任務中開銷最大的操作要歸咎于向GPU發送 SetPass call 的指令,減少它的請求次數是優化這類任務的最佳手段。
我們可以通過Profiler窗口中 Rendering的部分看到到底有多少SetPass call和batch被發送到GPU。當然,根據目標硬件的不同,對SetPass call的數量的承受度是不同的,比如PC客戶端能接受的數量要比移動設備多許多。
我們可以通過以下手段來減少SetPass call和 batch的數量:
減少被渲染物體的數量可以減少 SetPass call 和 batch的數量
減少被渲染物體的請求渲染的次數可以減少SetPass calls的數量
將被渲染物體的數據進行合批,可以減少batch的數量
針對這三條,我們進行展開
I . 如何減少被渲染物體的數量?
減少被渲染物體的數量是最簡單的方式來提升渲染性能表現,我們可以通過以下幾個方法:
減少在場景中相機可見(視錐體)的被渲染物體的數量。比如,如果我們渲染一群各不相同的角色,我們可以嘗試去掉幾個,然后看一下效果。這比用復雜的技術去進行優化來的快得多。
我們可以通過使用相機的 遠裁減平面(Far Clip Plane)屬性進行控制,這一點跟第一條的原理是一樣的。
我們可以通過改變相機的 遠近剔除(Layer Cull Distances)屬性來自定義對渲染對象的剔除距離。這種方法一般多應用于非常小的物體(比如草地上的花卉),一旦距離相機超過一定的距離,即使在相機的視錐體內,也不進行渲染。
我們還可以使用相機上面的 遮擋剔除(occlusion culling)選項,顧名思義,如果一個被渲染對象完全被另一個被渲染對象遮擋(相對于相機),那么它將不會被渲染。但是,occlusion culling 選項并不適用于所有場景,慎用。
II . 如何減少被渲染物體的請求渲染的次數?
我們都知道,實時光照,陰影和反射會給游戲增添許多真實感,但是也會產生巨大的開銷。因為他們會導致同一被渲染對象被多次渲染,這將大大影響性能。
其中就拿 渲染路徑(rendering path)來說,選擇什么樣的渲染路徑會產生非常大的差異。大多數情況下,如果我們的設備是比較高端的硬件設備,選擇 延遲渲染(Deferred Rendering)相比 前向渲染(Forward Rendering)要更合適,因為它的特性可以讓你使用更多的實時光照,陰影和反射。而前向渲染更適合低端的硬件設備上,同樣的渲染量上,它對于GPU的開銷沒有那么大。到底誰更好,具體情況具體分析。
動態光照 很昂貴,在優化方式上面也很復雜, 感興趣的小伙伴可以點擊前方傳送門。如果場景中有很多被渲染物體不會移動,可以考慮使用 光照烘培(baking)。這樣在游戲運行時就可以不用考慮動態光的計算。
陰影 的質量可以通過 Quality Settings 來進行設置,比如,我們可以通過設置陰影距離(Shadow Distance)來控制多少距離以內物體之間會投射陰影。
反射 的優化比較復雜,這里也不展開,留下傳送門。
III . 如何將被渲染對象進行合批,減少batch?
被渲染對象必須具備以下要素符合合批條件
共享同一材質實例
有相同的材質配置(貼圖,shader,shader參數)
盡管合批渲染對象可以提升渲染性能,但是也需要考慮如何確保合批產生的消耗不超過性能的收益。
以下是一些關于合批的方法:
靜態合批(Static batching),這種方法可以把鄰近的符合條件靜態的渲染對象進行合批。靜態合批會導致較高的內存占用,所以我們也需要考慮它的利弊。
動態合批(Dynamic batching)是另一種技術,允許unity非靜態的對象進行合批,但是有一些限制。同樣的,動態合批會導致CPU比較搞的內存使用,我們也需要權衡利弊。
UI方面的合批,UI元素相對來說有一些復雜, 它是受制于我們的UI層。
GPU instancing 選項可以讓許多同樣的渲染對象非常高效的合批。但是它受限于硬件設備。
Texture atlasing 圖集,可以把重復使用的圖片合并到一張更大的貼圖上。這個技術在2D游戲和UI系統中應用比較多,3D游戲也可以使用。Unity有一個內置圖集工具叫做 Sprite Packer。
我們還可以通過unity編輯或代碼人為地對網格和貼圖進行合并,當然這么做的話需要知道這些渲染對象的陰影,光照和剔除都仍然會各自處理。這意味著你通過合并材質達到提升性能的目的會與通過剔除渲染對象以至于不渲染它達到的效果相抵消。
我們需要注意在腳本中當通過 Renderer.material 來對材質進行操作,引擎會復制一份實例并返回它的引用,也就是說你的操作只會在它被復制的實例上進行,不會影響到它原來的材質,如果你想通過代碼來修改多個共享材質的渲染對象,你需要使用 Render.sharedMaterial 。
“Render中關于Unity渲染優化的方法是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。