Unity大密度建築場景載入解決方案

海洋_發表於2018-09-07

現在虛擬城市模擬,以及軍事模擬專案越來越多,開發此類專案,首先面對的一個比較棘手的問題是記憶體管理,城市中的建築物特別多,這些建築物的面數和貼圖都要被加到記憶體中的,記憶體有自己的峰值,超過了就要崩掉,所以記憶體的優化是必須要面對以及解決的問題。
Unity官方提供了Occlusion Culling的裁剪操作,網上有很多文章對它做了相關介紹,因為它是Unity自身提供的,對於我們程式設計師來說就是一個黑盒子,並不利於我們自己去進一步的優化,最好的方式就是自己通過程式碼重新實現一個Occlusion Culling演算法,當然對於城市模擬只做Occlusion Culling是不能完全解決問題的,我們需要從幾個方面入手搞定它,本篇博文就給讀者介紹這些針對密集建築物的優化。下面先看看虛擬模擬的場景:
這裡寫圖片描述
面對這麼複雜的場景,我們該如何去解決呢?本篇部落格教給開發者解決問題的方法,我們會從五個方面來實現我們的密集建築物解決方案。

AutoLOD

攝像機是用來裁剪的,我們可以設定攝像機的遠裁剪面距離做一些優化操作,當然如果是在飛行模擬,這種方法是不可取的,因為我們要求視野是足夠大的,這樣攝像機視錐體內的物體肯定會很多的,效率就會下降,解決這個問題很自然的想到LOD演算法,虛擬場景中的建築是非常多的,我們不可能讓美術幫我們把每個建築都進行減面處理,工作量是相當大的,LOD是根據攝像機的距離遠近相應的顯示不同面數的建築物,我們需要想一種能夠自動幫我做LOD處理的演算法,AutoLOD就是為解決這個問題而生的。LOD模型顯示如下所示:
這裡寫圖片描述

AutoLOD是Unity官方為我們提供了一個比較好的外掛,可以幫我們自動實現LOD演算法,進而對場景中的建築物進行優化,程式碼下載地址:
https://github.com/Unity-Technologies/AutoLOD
將其程式碼匯入到專案工程中後,然後需要我們做一些設定操作:
這裡寫圖片描述

這裡寫圖片描述

AutoLOD實現的效率比較高,佔的視訊記憶體少,測試的結果如下所示:

這裡寫圖片描述

其實我們還可以找到一種更好的演算法,結合AutoLOD演算法一起優化建築物的面數以及材質,也是第二個步驟要講解的內容——Amplify Impostors外掛,下面介紹Amplify Impostors外掛。

Amplify Impostors

這個是Asset store提供的解決方案,它的基本原理是根據攝像機的距離,將原物體生成一個模擬物體,模擬物體面數非常少的,外形跟原物體幾乎是一樣的,而且還可以旋轉,縮放,位移,並且可以投影,效果如下所示:
這裡寫圖片描述

模擬物件的生成,我們可以使用GPU例項化,該技術非常適合用於移動端,它對於面數的優化非常好,執行效率測試如下所示:
這裡寫圖片描述
在實際專案執行中,看一下樹木模型實現的效果圖如下所示:
這裡寫圖片描述
除了對模型的優化,我們還可以對紋理圖片進行優化,對應的是Amplify Texture。
程式碼下載地址:
連結:https://pan.baidu.com/s/1VKRwmn7QCzjIM0mqnq0RCA 密碼:yrko

Amplify Texture

Amplify Texture是一種紋理虛擬化,該技術可以繞過常見的紋理大小,數量和視訊記憶體限制,而不會影響質量,效能或大小。 使用Unity 2017,每個紋理最高可達16384 x 16384畫素。該技術處理幾百張貼圖都沒有任何問題。
這裡寫圖片描述
虛擬紋理的工作原理是將所有紋理切割成可管理的圖塊(或頁面),並將它們儲存在針對流媒體自定義資料檔案中; 在執行時, Amplify Texture始終使用可用的最大解析度虛擬化紋理,無論是8k或16k紋理(Unity 2017每紋理32k),原始大小永遠不會受到影響,虛擬貼圖其實就是一張大的圖集,中間會生成一張資料索引檔案,它存放了圖片的索引,大小,針對模型的ID資訊等等。根據模型的載入通過索引檔案在虛擬貼圖上查詢對應模型的貼圖,將對應的虛擬貼圖載入到記憶體中,將紋理對映到模型上面。
這裡寫圖片描述

技術實現參考網址:http://amplify.pt/unity/amplify-texture-2/

關於模型的優化技術差不多就講完了,運用上面的技術完全可以幫助我們處理密集型建築模型。下面還有一項重要的技術講解,也就是我們說的場景裁剪,我們使用的演算法也是Occlusion Culling。

Occlusion Culling

Occlusion Culling也是一種遮擋裁剪,可以將遮擋住的物體直接從記憶體中移除,或者從攝像機可視空間移除,這裡講的演算法與Unity自帶的Occlusion Culling是不一樣的,該演算法尤其對建築物密集的場景非常實用,先看看Occlusion Culling是如何工作的?如下圖所示:
這裡寫圖片描述
在此介紹兩種利用Occlusion Culling方法解決遮擋剔除的問題,首先介紹的方法是

Potentially visible set

參考網址:https://en.wikipedia.org/wiki/Potentially_visible_set
具體實現步驟如下所示:
1、地圖切割成Tile,Tile切割成Portal(視口)和Cell(大物件、中物件、小物件);
2、檢測場景物件所屬Cell,一個物件可以屬於多個Cell;
3、 利用蒙特卡洛方法Portal隨機一些起點,Cell隨機一些終點(根據大、中、小隨機不同數量的點);
4、 雙層遍歷每個Portal和Cell,射線檢測是否阻擋,如果阻擋,判斷阻擋物是否被在當前檢測Cell內,如果是,Cell可見;(注,當前設定兩個高度檢測)
5、 儲存檢測資料,執行時載入解析,根據玩家位置檢測當前Portal,然後遍歷場景所有Cell內Item,判斷顯示和隱藏;
總之:
此pvs方案相比於Unity OcclusionCulling,更適合大地圖比如5000米x5000米,pvs生成data基於Tile,支援動態載入,佔用記憶體忽略不計,同時CPU消耗也極少;

先看看沒有使用Occlusion Culling裁剪演算法之前,實現效果圖如下所示:
這裡寫圖片描述

應用了Occlusion Culling 演算法後,看看效果如下所示:
這裡寫圖片描述

通過上面兩幅圖的資料對比,可以看到Draw Call明顯減少了,優化效果還是非常明顯的,再看看另一種Occlusion Culling 演算法實現的效果。

IOC演算法

先把該演算法能實現的功能給讀者介紹一下:
1、實現建築物的裁剪
2、粒子效應遮擋剔除
3、燈光遮擋剔除
4、完全支援實時陰影
5、完全支援動態批處理
6、支援移動裝置上的密集場景處理

我們先看看對特效的遮擋剔除優化,在優化前的場景渲染,如下圖所示:
這裡寫圖片描述

優化後的遮擋剔除效果,如下圖所示:
這裡寫圖片描述

通過兩幅圖對比可以看到,Draw Call減少了一半多,當然我們還可以進一步去優化。

該演算法對於密集型建築同樣好用,同樣先展示一個沒有使用任何裁剪演算法的有密集物體的場景,Draw Call數量是非常大的。如下圖所示:
這裡寫圖片描述
經過我們的Occlusion Culling演算法後的裁剪效果,如下圖所示:
這裡寫圖片描述

Draw Call數量對比也是非常明顯的,還是有效果的。

總結:

以上給讀者介紹了針對密集型建築使用的解決方案,該方法在PC端,移動端都是適用的,最後把程式碼奉上,參考案例程式碼可以將其應用到自己的專案開發中。

程式碼下載地址:
連結:https://pan.baidu.com/s/1Uhp-eejG_7rA_hXz42cBVg 密碼:5ehf

參考網址:
https://blogs.unity3d.com/cn/2018/01/12/unity-labs-autolod-experimenting-with-automatic-performance-improvements/

相關文章