完美世界丁許朋:UE4開放世界ARPG《幻塔》技術分享
在2020虛幻引擎技術開放日中,來自完美世界《幻塔》遊戲開發工程師丁許朋,為大家帶來了《幻塔》遊戲的開發技術分享。
以下是演講實錄:
丁許朋:大家好,丁許朋,我現在完美世界幻塔工作室任客戶端引擎工程師。我今天結合我們遊戲《幻塔》來給大家做一些技術分享。我們遊戲是基於虛幻引擎4的MMORPG類型的遊戲,首先我們一起來看一段我們遊戲的視頻:
那麼從這個視頻中我們可以看出,我們遊戲主要有兩個特點:一個是開放世界,第二個就是高自由度。
那對於在移動平台做這種開放世界類的遊戲,我們會面臨著很多的技術問題。
第一個技術問題就是大世界,就我們的地圖目前有2.5K×2.5K,當然了對於現在的遊戲來說2.5Kx2.5K並不算大,但是當你的地圖達到一定程度的時候,我們面臨的技術問題其實是一樣的。
當然Unreal本身對大地圖提供了比較好的支持,比如說Unreal提供了流式關卡,流式關卡的意思就是我把大地圖切成小的地圖,然後按需載入。
在載入策略方面Unreal也提供了兩種:
第1種:觸髮式的地圖載入,觸髮式的地圖載入適合於,比如說你這個世界並不太連續,兩個世界之間有明顯的交界,我這個時間我可以在交接處放一個觸發盒子,比如說我走到這個地方,這個觸發盒子的時候去載入另一塊地圖。
第2種:世界合成器,就是World Composition,它裡邊可以分Layer,就是在這Layer裡邊我可以放不同的Level,這樣的話我可以根據Layer定義不同的載入策略,這樣的話會更靈活。
這是Unreal做的比較好的地方,當然Unreal也有做的不太好的地方,比如說Unreal的地形系統,那我們來看一下Unreal的地形系統。
在Unreal中 它的地形系統叫做Landscape,在右邊這張圖就是它的地形系統的創建界面,比如說我們可以就是調一些參數就可以創建出來,就在點擊這裡的Create 就可以創建出來一個地形,或者說在這個標籤里從外部導入一個高度圖來生成地形。
那麼跟地形相關的第一個概念就是Quad,那Quad就是Unreal就是地形系統的基本單位,它的大小呢跟Scale相關,那麼這個紅框圈出的地方就是Scale。
我們看它的單位這裡是顯示的是100,因為Unreal裡邊它的單位是厘米,所以說這100是一米,如果你不調這個參數的話,它的一個Quad就是相當於是一米見方的一個塊。
第二個跟地形相關的概念就是Section,這Section它是Quad的容器,也是地形LOD的基本單位,比如說地形LOD它計算的規則是就是高階的,低階LOD的擴展會減一半。
比如說第0級LOD是31×31,那麼第1級的LOD就是15×15個Quad,那目前我們可以看出來,每個Section就可以有7×7、5×15、31×31,一直到255×255,一共這6種可選。
那麼第三個跟Landscape相關的概念是Component,那Component是Setting的容器,它是UE4中地形繪製和地形裁剪的基本單位,目前它也是只有兩種配置:一個是1×1;一個是2×2。
就相當於是說一個Component只有1個Section,或者有4個Section。
那麼UE4這是個地形系統的優點,它是地形是統一管理,相當於是我一個Landscape的Actor就管理了所有的Landscape相關的Component。那麼它地形、地塊之間的數據耦合度比較小,它是以Component為單位就是執行LOD計算,因為它Component是比較獨立的,所以說它的計算可以並行起來,多線程來處理。
地形系統的缺點是什麼?因為它一個Component一個Actor管理了所有的Component,那這個Actor初始化的時候,所有的Component都已經初始化了,這樣會導致三個問題:
第1個問題:內存佔用會比較大,地形相關的內存佔用會比較大。
第2個問題:它會增加渲染線程的裁剪開銷,因為它這個Component在註冊的時候,它這個渲染代理就是SceneProxy都已經創建好了,就相當於是渲染線程在做剔除的時候,有可能你這個地形就是離玩家非常遠,它根本是不需要考慮,但是說它現在也需要考慮要不要把它裁掉。
第3個問題:當你視距比較大的時候,地形相關的Draw Call會非常高,增加了CPU的消耗。
這裡給大家舉個例子,比如說我這一個Component有4個section,那每個Section裡面是63×63的Quad組成的,當這個Component離玩家很遠的時候,它會退化成2×2的Quad,如果你這個Scale沒有改,你相當於是你還是1米×1米,相當於是這一個Component只覆蓋了2米×2米的大小,這樣會導致你這個視距裡面有非常多的Component。
在Unreal中一個Component會包含比如說剛才我們講的它是2個4×4,2×2 就是4個Section,如果這每個Section它的差別不太大,它會把這個4個Section合併成1個Draw Call,就相當於是1個Component。要麼是有1個Draw Call,要麼是有4個Draw Call,這樣會導致你視距很大的時候,你這個地形相關的Draw Call會非常高。
那麼針對這個問題,我們目前有三種解決方案:
第1種:我們可以調整地形的創建參數,讓地形生成的Component數儘可能的少。比如說我可以把Quad調大,然後可以把Section裡邊的Quad數量調多,讓它生成的Component的比較少。當然,這樣會帶來另一個問題,就是你這個地形Cutting(切割)的力度會變粗。
第2種:可以用虛擬紋理,就是說地形製作上使用虛擬紋理,虛幻引擎官方會在4.26版本的引擎上支持這個功能。相當於是一個Draw Call,就可以把所有的地形畫繪製完成。但是虛擬紋理它本身也是有消耗的,所以說它具體在Mobile(移動)平台表現怎麼樣,還需要進一步的測試。
第3種:對地形進行切割,切割本身也分兩種。第一種,用Houdini軟體來進行切割。第二種,自己寫了個工具來進行切割。
剛才我們所講到的是優化地形的Draw Call,對於地形的面數,我們目前的做法是用了LODBias。
例如在繪製地形的時候,這個地形是第零級,但我們偏移一級來畫,即用第一級來畫;那第一級地形,就用第二級來畫,以此類推。這樣的話很好地控制地形的面數。
我們看一下這張圖:
在這張圖中我們可以看到我這個視距是非常遠,我們可以看到地圖中的大部分的物件。我們在優化之前,我們那個地形的Draw Call有220多個,優化之後我們地形的Draw Call現在只有37個。
對於面數我們使用地形偏移,我們目前地形偏移了一級,偏移的話在這個視角下優化了大概15萬面,這個優化其實是相當可觀的。
那麼在進入第二個主題之前,我們來看一下就是移動平台的渲染管線。
移動平台由於硬體會有兩個限制,一個是頂點數受限,一個是Draw Call受限。
我們看一下這是移動平台的渲染管線,其實它這裡邊會有一個Tiling的過程,Tiling過程就相當於它VS先走一遍,然後決定這個三角形在哪個Tile裡邊,個時間它會把它臨時數據放到這個主存中,如果你的頂點太多,它這邊就會形成一個熱點。
第二個Draw Call受限,Draw Call提交的時候,CPU要準備大量的數據,而且提交Draw Call的時候會把這個Shader生成,編譯成對應平台的編碼。
所以說,我們在移動平台主要是這兩個限制,我們在做開放世界遊戲時,面對超大視距在角色這個位置的時候,我們能夠看到的地圖非常遠。
這樣會導致兩個問題:
第1個:要畫的東西非常多
第2個:頂點數也會非常多
而由於移動平台這兩塊都是受限的,相當於雖然你看到了這麼多東西,但是硬體其實是繪製不完的。
這就需要裁剪策略,提前把對視覺不重要的裁掉,Unreal也提供了好幾種裁剪方案:
第一種:距離剔除,即Distance Culling。根據你攝像機的遠近,來把它剔除掉。在每個X軸上設置一個剔除距離,對玩家交互不強的且視覺不重要的,就剔除掉。
第二種:視錐剔除,即Frustum Culling。把不在攝像機視野範圍之內的剔除掉。
第三種:預計算可見性,即Precomputed Visibility。先預先離線計算好,走到這個位置的時候,查詢這個計算好的表,哪些東西是可見的,哪些是不可見的。預計算可見性只適合靜態場景,主要的應用場景是室內。
第四種:動態遮擋查詢,即Dynamic Occlusion。針對於動態遮擋查詢Unreal提供了三種方案。
第1種:基於硬體的遮擋查詢,即Hardware Occlusion Queries。被查詢物會根據它的包圍盒提交一個Draw Call,來硬體做Depth Buffer,查一下它有沒有被遮擋住。這種方案它的缺點就是Draw Call會比較高。
第2種:HIZ的遮擋查詢,即Hierarchical Z-Buffer Occlusion。這種方法不需要提交Draw Call,它首先把Depth Buffer做mip,之後根據這個被查詢物的這個包圍盒再映射到屏幕空間,計算物體最長的邊,根據最長的邊來算一個它在哪個mip里做,然後在那個mip里做遮擋查詢。
這兩種都是基於硬體的方法,如果這個裁剪是CPU在做的話,它需要回讀到CPU,回讀的話會延遲一幀或者幾幀,這樣就導致了一個問題,因為延遲了所以裁剪是不準的。Unreal還提供了一種基於軟體的遮擋查詢。
第3種:軟體遮擋查詢,即Software Occlusion Queries。被查詢物先用CPU進行軟光柵化,作為軟光柵化來生成這個Depth Buffer,然後再來做遮擋查詢,這樣的好處就是它不需要回讀了。它全是用CPU來計算的,它具體性能表現怎麼樣,還需要一定的測試。
那麼對於開放世界的遊戲,另一個不得不提的主題就是植被系統了。如果你這個開放世界很大,但是植被很少的話,那你這個世界的細節不豐富。以前的植被系統都是實例化繪製的,就是Instance Static Mesh即ISM。
ISM的裁剪是它的主要問題,比如1000個物體,人物視野只看到了1個,但是這1000個物體都是要提交的。
所以說Unreal針對這個問題做了個Hierarchical的Instanced Static Mesh即HISM。它的實現是就是根據樹形結構來做了Cluster來分組,可以把裁剪粒度更精細,還可以做Cluster LOD,同時我還實現了距離剔除。
這些都是針對CPU的粗粒度剔除,對於GPU優化方面,Unreal提供了Early Z Pass。植被系統中樹、草都是Mask材質,Mask Material需要做Alpha test,所以Unreal目前的做法是把Mask材質先在Early Z Pass中深度畫一遍,利用這段時間已經完成了Alpha test,在Early Z Pass把Mask材質的Pixel過濾掉,這樣就優化了Mask材質。
其他減少Draw Call的方法:
第1個:動態批次合併,即Dynamic Instancing,這是4.2版本加入的功能,對於我們這個遊戲來說,開啟了態批次合併之後,優化了150個Draw Call左右。
第2個:Hierarchical LOD,即HLOD。例如一個大的關卡,可以生成一個代理,一個Draw Call把它畫出來。HLOD也有他的問題,它會導致你的包體跟內存變大。
對於開放世界遊戲,還有一個問題就是陰影,我們看到的東西很多,如果陰影繪製的距離很近,這樣就導致了場景很平,沒有層次感。Unreal在PC平台上提供了很多應用方案。
第1種:聯級陰影,即Cascade shadow map。
第2種:距離場陰影,即Distance field shadow。
Unreal官方建議,在近處用聯級陰影,在遠處用距離場陰影。
第3種:膠囊體陰影,即Capsule shadow。利用物理資產Physical Asset來生成陰影,這種實現有一個好處就是它支持間接光照。例如一個場景里全是烘焙的這種Lighting,聯級陰影是生成不了這種陰影的,但是膠囊體陰影可以對這種間接光也產生陰影,但是你要做的非常細的話,你需要很多膠囊體,這是它的一個缺點。
目前在移動平台上,UE4的陰影方案主要是兩種:
第1種:調製陰影,即Module Shadow。
第2種:級聯陰影,即Cascade shadow map
先來看調製陰影,先看這張圖:
調製陰影它其實它主要是跟場景做了簡單的乘積,它跟其他陰影混合的時候,是明顯的疊加效果,所以說這種基本滿足不了現在遊戲的品質要求。所以UE4在移動平台上只能選擇級聯陰影。級聯陰影最初是為了解決陰影貼圖的精度不夠而導致的透視堆疊。
根據這個圖說明,把視錐分為三級,再根據太陽方向,把小視錐包圍住,生成一個正交投影的矩陣,然後每一個級生成一個ShadowMap,這樣也更符合人類的這個視覺特點。
在UE4里級聯陰影的設置界面
設置界面包括了設置級數的、每一級結束了怎麼切換等等。
對於級聯陰影,它主要的問題是什麼?
主要的問題是因為,級聯陰影每一級都是一個視錐,它需要單獨做跟場景做裁剪,就是CPU內的裁剪消耗比較高;另一個是它級數很多,需要繪製的陰影的物件會很多,導致你的場景的Draw Call會比較高。
在移動平台上,由於帶寬受限,陰影貼圖做成1024這種解析度是一個比較合適的選擇,這樣就需要更多的級數去提高它的精度,但是由於之前講的幾點限制,所以在移動平台做不了這麼多級數。
針對級聯陰影的問題,我們現在的做法是用4級,前2級是全動態,後面2級是只畫靜態物體,前2級做分幀刷新,即不是每幀都提交,後面2級做低頻刷新,即隔幾幀才刷新一次。
通過這樣修改CSM,可以做到400M距離的陰影效果。
我們遊戲的第二個特點就是高自由度,在以前的遊戲中,人物與場景交互是很少的,當然隨著Unreal對物理引擎就是良好的封裝,為我們創建這種更高自由度的交互就是提供了可能。
我們遊戲中做了踩不同的地形和不同的物件,會有不同的聲音反饋,這樣更真實。還有不同的砍樹,踩水等交互,另外場景中大部分物體都是可以被推走或者破壞掉的。
那麼這種根據不同的交互產生不同聲音是怎麼做的呢?
我們地形分了4層,在草這一層,通過匹配對應的物理材質的聲音來實現。
例如砍樹,我們是全物理模擬的,而並不是簡單的播一個動畫。
例如砍草,整個世界大部分草是可以砍掉的,而且別的玩家是可以看到的,而不是簡簡單單的一個客戶端表現。
這是踩水,角色走在水裡邊會產生這種漣漪效果。
遊戲中大部分物件是可以被破壞掉,或者挪走等等。
為了製作出高自由度的遊戲,也因為UE4的Movement的組件本身提供了非常多的Movement mode,所以在飛行、游泳等之上,設計擴展出了攀爬滑板等模式。
攀爬
游泳
滑板
我們遊戲立項的時候,拿到的是虛幻4引擎4.20版本,目前我們升到了4.25,那隨著版本的迭代UE4,對移動平台的支持越來越好,比如說它添加了動態批次合併、骨骼實例化等等一些新功能。我們相信隨著UE4對移動平台支持越來越好,以後會湧現出越來越多的基於UE4的精品遊戲,謝謝大家。
?·····?End?·····
GameLook每日遊戲產業報道
全球視野 /?深度有料
爆料 / 交流 / 合作:請加主編微信?igamelook