當前位置:編程學習大全網 - 源碼下載 - 團結開世界,如何優化土地?

團結開世界,如何優化土地?

大地形數據加載方案

考慮到現有的內存機制,大地形加載無法壹次性添加到內存中。這個問題很明顯。其實在遊戲開發中經常會遇到,比如我們常見的進度條。加載進度條的目的是等待程序加載場景,進度條只是壹個遮罩。加載大地形除了封鎖沒有別的辦法。這是大方向,那麽作為壹個節目,怎麽屏蔽呢?這個街區有多大?我們需要根據要求來劃分這些具體問題。比如飛行模擬器塊的大小可能更大,因為鳥瞰圖更大,場景漫遊塊可以更小等等。我們先以遊戲經典《魔獸世界地形加載方案》為例,向讀者介紹壹下它的實現原理。魔獸世界的遊戲實現了無縫地圖的拼接,所以很有參考價值,如下圖所示:

魔獸世界如何實現無限地圖?其實也是很多場景塊的拼接。我們通過編輯器分析魔獸世界中地形塊的大小劃分。魔獸世界場景,我們稱之為地圖世界,由壹系列地圖瓦片組成,大小為1600/3 ≈ 533.33m,每個地圖瓦片由16x16 MapChunk組成,從中我們可以計算出每個地圖。然後是由9x9+8x8地形頂點高度、法線和若幹貼圖層(壹般4層)組成的表面紋理。這裏不討論魔獸世界的地形大小,但是可以借鑒壹下它分塊的思路。

繼續分析魔獸世界的分塊方式:按照矩陣劃分,在XZ平面上進行。每個塊將包含某些信息數據,例如XZ (3,3)位置處的地圖塊,並且每個地圖塊包含在地圖塊中使用的地圖和模型示例。所謂模型實例,也就是我們的道具,可以理解為瓷磚中同壹模型的不同擺放位置、大小、角度的信息,都保存在二進制文件中。為了節省文件大小,模型實例通過索引模型保存,類似於頂點索引。每個貼圖片中還有貼圖信息,如貼圖名稱和UV信息。本課程的方塊思維模式類似於魔獸世界,後面章節會詳細介紹。分塊之後,下面是實現原理。

實現原理:在任何時刻,程序總是在播放器內部和周圍保持3x3的地圖瓦片。隨著玩家的移動,這些地圖瓦片將被動態更新,並且新的地圖瓦片將被加載以替換未安裝的舊地圖瓦片。為了提高調度效率,魔獸引入了緩存機制,緩存最多存儲16個MapTile數據。當妳需要加載壹個新的地圖時,妳將首先在緩存中查找它;未安裝的舊地圖分塊不會立即刪除,但會保存在緩存中以備調用。因為玩家的活動範圍在壹段時間內通常不會有太大變化,所以這種緩存策略在應用中表現得非常好,這是無縫地圖的基本原理。地形的動態加載和卸載將通過多線程來實現,我們將集成兩個線程:壹個線程專用於加載地形,另壹個線程專用於卸載或隱藏地形MapTile。我們來回憶壹下經典遊戲,遊戲場景效果如下:

本課程實現的方法可以用兩種方式處理加載和顯示塊的問題。壹種方式是使用對象池預加載劃分好的地形,根據視距檢測判斷顯示哪些塊並隱藏,此處不刪除。所以只需要壹個線程。另壹種方式是使用多線程,壹個線程專門用於移除和卸載不在視線範圍內的情節,這樣可以提高效率。下面是壹個使用多線程的加載方案。

大地形加載方案的多線程實現

多線程在PC端遊戲中應用廣泛。比如可以設置壹個線程來加載資源,在遊戲服務器中也會用到。這裏向讀者介紹多線程的實現方案。多線程處理的問題就是把所有的加載邏輯放到壹個新的進程中,和主線程做壹些進程間的通信,接受主線程的加載建議,做按需加載,同時也提前做壹些預加載,放到分配的內存中,就像魔獸世界的處理方法壹樣。主遊戲進程總是需要維護很小的內存,大量的內存數據在另壹個進程中處理。這樣就可以優化大地形塊的加載,實現方法如下:

第壹,主線程會加載九塊地形,主線程只負責維護這九塊地形。無論角色如何移動,角色所在的整個區域永遠是九塊地形。如上圖所示,這九塊可以由主線程直接加載到內存中,剩下的16塊會通過另壹個線程放入緩存中。角色的位置在已經加載的九塊地形中間,也就是A所在的位置。隨著角色的移動,會添加新的地形塊,並替換現有的地形塊,這樣會壹直顯示9個地形塊。被替換的地形不會立即卸載,而是根據角色的移動進行預測。它會等待主線程通知它按照壹定的規則卸載和裝載陸塊。其實這種實現方式就是我們通常所說的雙緩存——多線程技術。取得的效果如下:

地形分塊加載後,要考慮地形上的紋理映射,地形的映射資源也會占用很大內存。下面介紹如何加載海量測繪數據。

大地形海量圖片加載方案

大地形中有很多場景圖片,地形中至少有四層地圖。加載這麽多地圖需要考慮這些因素,屏蔽的時候也需要考慮這些因素。此外,場景中使用的光照貼圖烘焙也是需要考慮的問題。為了緩解內存壓力,我們會提前把地形素材和建築素材分塊打包。如何先分塊加載場景貼圖?它是這樣實現:

這個想法是根據我們劃分的區塊,把場景中的地圖做成不同的地圖集。當然,兩個區塊的地圖也可以做成地圖集。對於PC端,最大圖集尺寸為4096,對於移動端,最大圖集尺寸為2048。這也是為了避免頻繁的加載和卸載內存會導致大量的內存碎片,不利於以後大內存的分配。在繪制圖集之前,我們需要做的是在地形塊中的紋理貼圖和我們打包的圖集之間建立壹壹對應關系,以便於對號入座。因為我們打包的圖集與實際地形無關,為了建立它們之間的對應關系,我們需要在其中有壹個完整的索引文件表,它是圖集與實際地形紋理之間的橋梁。通過我們建立的索引文件,可以找到實際地形紋理和圖集紋理的對應關系,我們建立的索引表是要加載到內存中的。但是,我們的圖集是在加載任務之後才添加到內存中的,這就要求我們的索引文件要盡可能的少,因為它們是來自內存常駐的。除了海量圖片的加載,我們還需要處理密集建築的加載。

-密集建築物的裝載方案

密集建築加載,試想壹下,如果把場景中的所有建築壹次性加載到內存中,內存瞬間就滿了,幀數瞬間下降,這也是為什麽妳在遊戲場景中移動的時候,遇到密集建築會卡死的原因。以前用LOD處理,對於遮擋物體用簡單模型,也會增加內存的負載效應。如果人物不停的在建築之間來回穿梭,不同的LOD模型就需要來回切換,對內存也是壹種負擔,效果也不理想。如何解決這些程序員必須解決的問題?很多人想到合並大網格,這是不可行的。大網格不適合裁剪操作。想象壹下,如果相機只看合並後網格的壹小部分,它們需要壹起加載到內存中,因為它們是壹個整體,但實際上我們並不需要那麽多模型數據。在合並網格的時候,我也想給讀者壹個建議,盡量把靠在壹起的模型合並,避免上述問題。其實最有效的解決方法就是分塊,可以利用地形分塊的思想來進行,地形分塊與地形分塊密切相關,每個地形分塊中的建築隨地形分塊壹起加載。如果街區內的建築物非常密集,這種方法是無法完全解決的,需要進壹步的處理,即加入OC遮擋算法結合LOD算法,這樣我們目前的問題就可以完全解決,這也是課程。

為了說明方法,進壹步的優化方法是把OC遮擋算法和LOD算法放到GPU中進行計算,這樣效率會提高。在Siggraph2015中,發表了壹篇GPU驅動的渲染管道的文章。它的思路是使用GPU進行遮擋裁剪,主要分為兩個階段,使用DX12圖形API,如下圖所示:

它的思路是第壹步先做壹個粗略的遮擋裁剪列表,然後根據視線距離或者光線檢測進壹步細化裁剪操作。這個思路類似於我們的碰撞檢測算法,引擎中的碰撞檢測算法也是基於這個原理實現的。我給讀者介紹壹下:實際可用的碰撞檢測算法壹般分為兩個階段:

第壹階段,broad phase快速找出潛在碰撞對象對的列表,不在這個列表中是絕對不可能發生碰撞的。Broad phase已經確定了壹些需要進壹步檢查的目標對。

在第二階段,窄階段精確地找出碰撞物體對的列表。因為前壹階段的壹些物體對實際上並沒有發生碰撞,所以這壹階段需要消除。

broad階段的壹個簡單算法叫做掃描和修剪(SAP ),它本質上使用了排序算法。第壹步,初始化排序列表,列表中的元素是包圍盒,可以用任何排序算法完成,比如快速排序;之後的排序不是靠快速排序,而是靠冒泡。為什麽冒泡排序比較好?是因為壹個默認的前提:物體的運動具有時間上的連貫性,即當前幀和下壹幀的位置是接近的,所以在冒泡排序過程中,位置交換預計會非常接近。

其實算法上有很多相似之處,這裏要互相借鑒解題思路來解決我們的問題。我曾經做過壹款端遊,端遊中的很多優化思路也適用於移動端。與PC端相比,移動端只是壹臺配置較低的電腦。然後我們繼續向讀者介紹我們的遮擋裁剪,論文作者也做了效率測試。以250000個對象和1G網格為例,測試結果如下:

這不是很酷嗎?它可以用來解決項目開發中的問題。先說用GPU優化我們的地形場景。

GPU大地形渲染優化解決方案

首先,我們的地形會有自己的地表圖。常用的曲面貼圖是四種紋理的融合,最多可以有八種。地形紋理渲染會涉及LOD算法,遠處的地形網格可以簡化,對應的地圖也是最低的。這是MipMap的用法。此外,必須有草,花和許多其他類似的物體來渲染。先說草和花的畫法。他們在遊戲中會非常多。常見的做法是穿過引擎提供的面片或者穿過三張圖片,然後將上面有Alpha通道的貼圖進行貼圖,如下圖所示:

CPU畫這些草或者花在PC上是可以的,因為現在電腦都是多核,會影響手機上的效率。用CPU畫圖,會有很多DrawCall,草或者花還需要擺動,計算量大,嚴重影響運行效率。如果CPU有困難,GPU可以幫忙,我們可以在GPU裏放草或者花來執行。效果如下:

  • 上一篇:Weblogic部署源代碼
  • 下一篇:如何用C語言創建和刪除文件
  • copyright 2024編程學習大全網