在Unity中對森林植被進行優化


創建3D森林的時候不僅需要關注藝術技巧,更需要了解擁有什么資源以及如何進行放置。其中最重要一項需要考慮是:一個茂密森林的密度以及隨之而來的性能優化。

 
 

問題

解決森林優化的方法有很多,但是關於如何創建資源的通用指南卻不多。不過關於森林優化有一樣事情是共通的,即頭號敵人都會是繪制調用(Draw Call)。

 
 

雖然多邊形數量也很重要,但是問題並沒有那么復雜。你只需要知道一個合理的目標值。

下面是一些我所制作的植物資源以及它們的多邊形數量,可作為對應合理數字的參考。如果發現需要大量的Alpha Card才能獲得所需的樹冠豐茂程度,你可以在紋理中增加樹葉的覆蓋量。

 
 

還有過度繪制(Overdraw),當在Alpha Card和對象之間存在大量重疊時會發生過度繪制。我沒有考慮或關注過它,我不打算修改樹的輪廓以減少重疊。實際上,我不會為除了使它們看上去更美之外的任何原因去修改樹木的輪廓。我也不打算修改森林的布局,以避免植物重疊。讓森林真實而又不必操心過度繪制太難了。所以我把精力主要集中到了降低多邊形數量和繪制調用上。

 
 

計划

要解決這個問題,我們需要一個計划。大多數的計划要求在開始創建森林的時候,就考慮到優化策略。如果森林由來自不同來源的資源組成,可能很難做到這一點。減少繪制調用的策略有很多,在本文中我將分享我所使用的策略。

我的目標是將LOD1網格(第二個LOD階段)組合為巨型網格,這樣當玩家移動到遠處時就可以整合繪制調用。我計划中的第一步是讓森林里的所有東西,或者可能接近的東西都使用同一個材質。

森林中所使用到的資源都共享同一種材質。因此我需要所有的植被從同一個材質采樣。

 
 

選擇這樣做的原因,是因為可以確保任何一簇的植被資源在合並時,都能成功整合成一個繪制調用。如果每棵樹或草都使用唯一的材質,合並后的網格可能會擁有許多子網格,從而產生許多繪制調用。

我為需要的資源准備了一個2048x2048的區域,然后在創作的過程不停地將它們添加進去。這個過程是可以自動化,需要通過腳本修改所有植被資源的UV,不過有時候手工的方式效率更高。

分組

最終的目標是合並,但首先需要確定合並的方式。生成一個超級大的網格不是什么好主意,這有二個原因:

  • Unity中的網格索引緩沖區是16位的,這意味着每個網格最多只能有64k頂點。

    請注意:Unity2017.3及以上版本已經正式支持32位的索引緩沖,所以這已經不是問題。

  • 無法對單獨的分組使用LOD或從視錐體和遮擋剔除中獲益,因為整個森林將是一整個網格。繪制調用將會很好很少,但是三角形數量可能多得嚇人。我們還是可以用一些額外的繪制調用去拯救大堆的三角形的。

進入六邊形網格。我編寫了一個腳本,把所有的植物自動分到一個個六邊形網格中。我選擇了六邊形而不是正方形,是因為六邊形更接近圓,在進行玩家和每組之間的距離檢測時可以更加精確。如果使用正方形,則會有一些角落離玩家太近。

 
 

六邊形分組隨后會被組成一個個超級六邊形。在一個特定超級六邊形中的每個常規六邊形都是處於LOD2狀態,超級六邊形會切換到一個合並版本的LOD2六邊形,進一步整合繪制調用。

為什么不簡單的使第一個六邊形網格中擁有更大的六邊形呢?因為更小的六邊形可以在過渡到遠的LOD時,能擁有更好的粒度控制,以及更精確的剔除。當物體足夠遠,多邊形夠低時,它們可以被合並成更大的六邊形。

合並

在最初構建系統的時候,我合並了LOD0以及LOD1,但這樣占用的內存太多。它會使高多邊形版本植被資源的頂點都擁有唯一的內存占用,因為每一個合並的網格都是唯一的。此外網格越大,視錐體剔除效果就越差,最后導致更多額外的三角形被繪制。很可能會離LOD0六邊形很近,或站在它們之上,因此視錐體剔除不精確的問題會更加突出。

我發現僅合並LOD1可以達到最佳平衡。LOD1多邊形足夠低,占用內存少,但節約的資源最多,所以我加載的世界其大部分將是處於LOD1狀態的。

在Unity中進行網格合並沒那么輕松。我必須要自己編寫腳本,因為資源商店里的那些腳本無法處理子網格或頂點顏色。我選擇不使用內置的LOD組件,因為它也僅是一個數據容器而已,六邊形分組會處理LOD切換。我簡單的使用了一個MonoBehaviour,並引用了處於未激活狀態的子游戲對象,這樣可以輕松的從渲染器獲得材質與子網格了。

 
 

使用六邊形組進行LOD化和剔除

有件重要的事情要了解:Unity內置的LOD組件性能不佳。特別是當所有的草叢上都有這個組件的時候,在CPU上會進行有許多的距離檢測。將世界划分為整潔的六邊形組有很多好處,其中之一就是可以對每一個組進行距離檢測,而非每一個子對象。然后將整個組的LOD都設成一致。我甚至還有一個用了着色器中的Alpha cutoff屬性的動畫過渡。

 
 

 
 

分組的另一個用途是作為一種動態遮擋剔除來使用。我不使用Unity的內置遮擋剔除,因為覺得它與多場景兼容的不是太好。分組數量不多,在運行時完全可以對它們進行幾個射線投射,確定六邊形組是不是在視圖中被完全遮擋。

我沒有在每一幀進行這些射線投射,我僅僅在翻過山丘和拐彎時會提前留些余量做檢測。不可能對所有對象這么做,成本太高。但對一個由20-50個對象組成的組做一些射線投射,還是可行的,特別是這些檢測隔幾幀才做一次。我只對地形進行遮擋檢測,因為一個森林里沒有什么東西能夠確保是被完全遮擋的。

 
 

創作平滑LOD過渡

一個平滑的LOD0到LOD1的過渡通常要比一個基於LOD0的低多邊形要好。如果過渡夠漂亮,就可以把LOD距離移得更近些,從而減少屏幕上的總多邊形數量。

我特別為樹木做的一件事就是按照LOD1的樣子進行創作。我使用3D包中的樹枝實例來構建樹。這使我可以為一些單獨的樹枝做一個LOD模型,然后通過將所有實例更新為更低多邊形的版本,創造完整的LOD1。

 
 

地形

地形有點超出了本文討論范圍,請注意:我沒有使用Unity的內置地形系統,因此我的所有植物都是常規的游戲對象。

我選擇使用常規網格而非地形系統,有三個原因:

  • 默認的Unity地形系統性能不佳,它會產生數百個額外的繪制調用和上千個分布糟糕的多邊形。使用常規網格可以按照需求來控制多邊形分布。

  • 為默認地形系統編寫着色器很受限制。

  • 我有許多的洞和懸垂物。我使用的着色器非常簡單,它是一個帶宏覆蓋和法線的三通道Vertex Splat。

 
image

底紋

使植物着色器的一般性能,又稱為像素填充率合理優化十分重要。

如果使用的是延遲渲染路徑,那么將植物着色器完全延遲可以節省大量的渲染時間。我曾使用的是正向渲染,當我了解如何讓相同的着色器使用延遲渲染之后,節省了30%的渲染時間。

創建具有半透明度的完全延遲着色器並不簡單,因為需要訪問通常在延遲着色器程序里無法訪問的光線衰減。我使用了一個帶自定義光照模型的表面着色器,它把一個非常低保真度半透明遮罩寫入到G-Buffer中未使用的2位 (RT2的alpha)。然后我在Internal-DeferredShading.shader里添加了半透明函數。

光照烘焙

為森林中的所有植物烘焙光照將會產生很大的光照貼圖內存使用量,在生產階段難以接受的烘焙時間,而且最后結果看起來也並不是那么好,因為Alpha Card通常不會生成太好的烘焙效果。我將光照探頭用於比建築物小的任何東西。我為樹使用光照探頭代理體,這樣樹冠部分就能有一個到更淺顏色的漂亮漸變。

由於樹不是靜態對象,因此無法被光線映射器所見。我需要一種可以手動將探頭包圍區域變暗的方式。我編寫了一個簡單的腳本,將某個給定代理體內所有探頭按所選的顏色進行染色。

 
image

其它技巧

對樹的上半部分使用LOD1: 有些樹足夠的高,你可以讓樹冠部分保持低多邊形。

枯樹,或沒有樹冠的樹干:想要達到想要的樹冠密度,在沒有樹冠的情況下增加樹干是一種可以使森林看起來更厚的節約做法。

巨量面片資源 :在地圖中較平坦的部分,可以將大量草的面片合成單個對象,從而減少繪制調用,即使目標對象還處於LOD0/未合並狀態。

總結

下面是對茂盛森林與植被進行的性能優化的總結。

  • 繪制調用很可能會成為最大的問題。你需要有一個計划去減少它們。

  • 多邊形數是相對簡單的問題,只要確保每個資源的三角形數量合理。

  • 我忽略了對於過渡繪制的考慮,因為無法在不破壞美觀的前提下做到它。

  • 所有的植被紋理都圖集化到了一個材質,確保合並網格能成為單個繪制調用。

  • 我使用分組系統,將所有網格的LOD1都合並到一個組里。

  • 我沒有合並LOD0,因為它們的多邊形太高,占用太多內存。

  • 分組不能太大,否則無法從視錐體或遮擋剔除中獲益。

  • 我使用自定義的LOD化腳本,因為我是根據分組而非對象進行LOD切換。

  • 我使用自定義的網格合並腳本,處理頂點顏色和子網格。

  • 我手工制作的植被資源,經常在提前做好LOD1的計划。

  • 可以將Alpha cutoff動畫化,制作更平滑的過渡。

  • 我使用常規網格,而非Unity的內置地形系統。

  • 我編寫了一個完全延遲的植物着色器,以保持低像素填充率。

  • 我使用光照探頭來為森林提供照明,並為森林中的包圍區域使用自定義染色體。

以上內容就是在經過多次試錯后形成的結果,我將它用於世界中的許多對象,並不僅僅是針對植被。當有許多同類對象時,例如:木桶或岩石,它也能工作得很好。最好的情況下,一個對象的多個實例會被整合到單個繪制調用,而最壞的情況下,也僅是跟原先保持相同數量的繪制調用而已,不過會消耗更多的內存。



作者:何三思
鏈接:https://www.jianshu.com/p/f6dad566746a
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM