在Unity中对森林植被进行优化
創(chuàng)建3D森林的時候不僅需要關(guān)注藝術(shù)技巧,更需要了解擁有什么資源以及如何進行放置。其中最重要一項需要考慮是:一個茂密森林的密度以及隨之而來的性能優(yōu)化。
問題
解決森林優(yōu)化的方法有很多,但是關(guān)于如何創(chuàng)建資源的通用指南卻不多。不過關(guān)于森林優(yōu)化有一樣事情是共通的,即頭號敵人都會是繪制調(diào)用(Draw Call)。
雖然多邊形數(shù)量也很重要,但是問題并沒有那么復(fù)雜。你只需要知道一個合理的目標值。
下面是一些我所制作的植物資源以及它們的多邊形數(shù)量,可作為對應(yīng)合理數(shù)字的參考。如果發(fā)現(xiàn)需要大量的Alpha Card才能獲得所需的樹冠豐茂程度,你可以在紋理中增加樹葉的覆蓋量。
還有過度繪制(Overdraw),當在Alpha Card和對象之間存在大量重疊時會發(fā)生過度繪制。我沒有考慮或關(guān)注過它,我不打算修改樹的輪廓以減少重疊。實際上,我不會為除了使它們看上去更美之外的任何原因去修改樹木的輪廓。我也不打算修改森林的布局,以避免植物重疊。讓森林真實而又不必操心過度繪制太難了。所以我把精力主要集中到了降低多邊形數(shù)量和繪制調(diào)用上。
計劃
要解決這個問題,我們需要一個計劃。大多數(shù)的計劃要求在開始創(chuàng)建森林的時候,就考慮到優(yōu)化策略。如果森林由來自不同來源的資源組成,可能很難做到這一點。減少繪制調(diào)用的策略有很多,在本文中我將分享我所使用的策略。
我的目標是將LOD1網(wǎng)格(第二個LOD階段)組合為巨型網(wǎng)格,這樣當玩家移動到遠處時就可以整合繪制調(diào)用。我計劃中的第一步是讓森林里的所有東西,或者可能接近的東西都使用同一個材質(zhì)。
森林中所使用到的資源都共享同一種材質(zhì)。因此我需要所有的植被從同一個材質(zhì)采樣。
選擇這樣做的原因,是因為可以確保任何一簇的植被資源在合并時,都能成功整合成一個繪制調(diào)用。如果每棵樹或草都使用唯一的材質(zhì),合并后的網(wǎng)格可能會擁有許多子網(wǎng)格,從而產(chǎn)生許多繪制調(diào)用。
我為需要的資源準備了一個2048x2048的區(qū)域,然后在創(chuàng)作的過程不停地將它們添加進去。這個過程是可以自動化,需要通過腳本修改所有植被資源的UV,不過有時候手工的方式效率更高。
分組
最終的目標是合并,但首先需要確定合并的方式。生成一個超級大的網(wǎng)格不是什么好主意,這有二個原因:
-
Unity中的網(wǎng)格索引緩沖區(qū)是16位的,這意味著每個網(wǎng)格最多只能有64k頂點。
請注意:Unity2017.3及以上版本已經(jīng)正式支持32位的索引緩沖,所以這已經(jīng)不是問題。
-
無法對單獨的分組使用LOD或從視錐體和遮擋剔除中獲益,因為整個森林將是一整個網(wǎng)格。繪制調(diào)用將會很好很少,但是三角形數(shù)量可能多得嚇人。我們還是可以用一些額外的繪制調(diào)用去拯救大堆的三角形的。
進入六邊形網(wǎng)格。我編寫了一個腳本,把所有的植物自動分到一個個六邊形網(wǎng)格中。我選擇了六邊形而不是正方形,是因為六邊形更接近圓,在進行玩家和每組之間的距離檢測時可以更加精確。如果使用正方形,則會有一些角落離玩家太近。
六邊形分組隨后會被組成一個個超級六邊形。在一個特定超級六邊形中的每個常規(guī)六邊形都是處于LOD2狀態(tài),超級六邊形會切換到一個合并版本的LOD2六邊形,進一步整合繪制調(diào)用。
為什么不簡單的使第一個六邊形網(wǎng)格中擁有更大的六邊形呢?因為更小的六邊形可以在過渡到遠的LOD時,能擁有更好的粒度控制,以及更精確的剔除。當物體足夠遠,多邊形夠低時,它們可以被合并成更大的六邊形。
合并
在最初構(gòu)建系統(tǒng)的時候,我合并了LOD0以及LOD1,但這樣占用的內(nèi)存太多。它會使高多邊形版本植被資源的頂點都擁有唯一的內(nèi)存占用,因為每一個合并的網(wǎng)格都是唯一的。此外網(wǎng)格越大,視錐體剔除效果就越差,最后導(dǎo)致更多額外的三角形被繪制。很可能會離LOD0六邊形很近,或站在它們之上,因此視錐體剔除不精確的問題會更加突出。
我發(fā)現(xiàn)僅合并LOD1可以達到最佳平衡。LOD1多邊形足夠低,占用內(nèi)存少,但節(jié)約的資源最多,所以我加載的世界其大部分將是處于LOD1狀態(tài)的。
在Unity中進行網(wǎng)格合并沒那么輕松。我必須要自己編寫腳本,因為資源商店里的那些腳本無法處理子網(wǎng)格或頂點顏色。我選擇不使用內(nèi)置的LOD組件,因為它也僅是一個數(shù)據(jù)容器而已,六邊形分組會處理LOD切換。我簡單的使用了一個MonoBehaviour,并引用了處于未激活狀態(tài)的子游戲?qū)ο?#xff0c;這樣可以輕松的從渲染器獲得材質(zhì)與子網(wǎng)格了。
使用六邊形組進行LOD化和剔除
有件重要的事情要了解:Unity內(nèi)置的LOD組件性能不佳。特別是當所有的草叢上都有這個組件的時候,在CPU上會進行有許多的距離檢測。將世界劃分為整潔的六邊形組有很多好處,其中之一就是可以對每一個組進行距離檢測,而非每一個子對象。然后將整個組的LOD都設(shè)成一致。我甚至還有一個用了著色器中的Alpha cutoff屬性的動畫過渡。
分組的另一個用途是作為一種動態(tài)遮擋剔除來使用。我不使用Unity的內(nèi)置遮擋剔除,因為覺得它與多場景兼容的不是太好。分組數(shù)量不多,在運行時完全可以對它們進行幾個射線投射,確定六邊形組是不是在視圖中被完全遮擋。
我沒有在每一幀進行這些射線投射,我僅僅在翻過山丘和拐彎時會提前留些余量做檢測。不可能對所有對象這么做,成本太高。但對一個由20-50個對象組成的組做一些射線投射,還是可行的,特別是這些檢測隔幾幀才做一次。我只對地形進行遮擋檢測,因為一個森林里沒有什么東西能夠確保是被完全遮擋的。
創(chuàng)作平滑LOD過渡
一個平滑的LOD0到LOD1的過渡通常要比一個基于LOD0的低多邊形要好。如果過渡夠漂亮,就可以把LOD距離移得更近些,從而減少屏幕上的總多邊形數(shù)量。
我特別為樹木做的一件事就是按照LOD1的樣子進行創(chuàng)作。我使用3D包中的樹枝實例來構(gòu)建樹。這使我可以為一些單獨的樹枝做一個LOD模型,然后通過將所有實例更新為更低多邊形的版本,創(chuàng)造完整的LOD1。
地形
地形有點超出了本文討論范圍,請注意:我沒有使用Unity的內(nèi)置地形系統(tǒng),因此我的所有植物都是常規(guī)的游戲?qū)ο蟆?/p>
我選擇使用常規(guī)網(wǎng)格而非地形系統(tǒng),有三個原因:
-
默認的Unity地形系統(tǒng)性能不佳,它會產(chǎn)生數(shù)百個額外的繪制調(diào)用和上千個分布糟糕的多邊形。使用常規(guī)網(wǎng)格可以按照需求來控制多邊形分布。
-
為默認地形系統(tǒng)編寫著色器很受限制。
-
我有許多的洞和懸垂物。我使用的著色器非常簡單,它是一個帶宏覆蓋和法線的三通道Vertex Splat。
底紋
使植物著色器的一般性能,又稱為像素填充率合理優(yōu)化十分重要。
如果使用的是延遲渲染路徑,那么將植物著色器完全延遲可以節(jié)省大量的渲染時間。我曾使用的是正向渲染,當我了解如何讓相同的著色器使用延遲渲染之后,節(jié)省了30%的渲染時間。
創(chuàng)建具有半透明度的完全延遲著色器并不簡單,因為需要訪問通常在延遲著色器程序里無法訪問的光線衰減。我使用了一個帶自定義光照模型的表面著色器,它把一個非常低保真度半透明遮罩寫入到G-Buffer中未使用的2位 (RT2的alpha)。然后我在Internal-DeferredShading.shader里添加了半透明函數(shù)。
光照烘焙
為森林中的所有植物烘焙光照將會產(chǎn)生很大的光照貼圖內(nèi)存使用量,在生產(chǎn)階段難以接受的烘焙時間,而且最后結(jié)果看起來也并不是那么好,因為Alpha Card通常不會生成太好的烘焙效果。我將光照探頭用于比建筑物小的任何東西。我為樹使用光照探頭代理體,這樣樹冠部分就能有一個到更淺顏色的漂亮漸變。
由于樹不是靜態(tài)對象,因此無法被光線映射器所見。我需要一種可以手動將探頭包圍區(qū)域變暗的方式。我編寫了一個簡單的腳本,將某個給定代理體內(nèi)所有探頭按所選的顏色進行染色。
image其它技巧
對樹的上半部分使用LOD1: 有些樹足夠的高,你可以讓樹冠部分保持低多邊形。
枯樹,或沒有樹冠的樹干:想要達到想要的樹冠密度,在沒有樹冠的情況下增加樹干是一種可以使森林看起來更厚的節(jié)約做法。
巨量面片資源 :在地圖中較平坦的部分,可以將大量草的面片合成單個對象,從而減少繪制調(diào)用,即使目標對象還處于LOD0/未合并狀態(tài)。
總結(jié)
下面是對茂盛森林與植被進行的性能優(yōu)化的總結(jié)。
-
繪制調(diào)用很可能會成為最大的問題。你需要有一個計劃去減少它們。
-
多邊形數(shù)是相對簡單的問題,只要確保每個資源的三角形數(shù)量合理。
-
我忽略了對于過渡繪制的考慮,因為無法在不破壞美觀的前提下做到它。
-
所有的植被紋理都圖集化到了一個材質(zhì),確保合并網(wǎng)格能成為單個繪制調(diào)用。
-
我使用分組系統(tǒng),將所有網(wǎng)格的LOD1都合并到一個組里。
-
我沒有合并LOD0,因為它們的多邊形太高,占用太多內(nèi)存。
-
分組不能太大,否則無法從視錐體或遮擋剔除中獲益。
-
我使用自定義的LOD化腳本,因為我是根據(jù)分組而非對象進行LOD切換。
-
我使用自定義的網(wǎng)格合并腳本,處理頂點顏色和子網(wǎng)格。
-
我手工制作的植被資源,經(jīng)常在提前做好LOD1的計劃。
-
可以將Alpha cutoff動畫化,制作更平滑的過渡。
-
我使用常規(guī)網(wǎng)格,而非Unity的內(nèi)置地形系統(tǒng)。
-
我編寫了一個完全延遲的植物著色器,以保持低像素填充率。
-
我使用光照探頭來為森林提供照明,并為森林中的包圍區(qū)域使用自定義染色體。
以上內(nèi)容就是在經(jīng)過多次試錯后形成的結(jié)果,我將它用于世界中的許多對象,并不僅僅是針對植被。當有許多同類對象時,例如:木桶或巖石,它也能工作得很好。最好的情況下,一個對象的多個實例會被整合到單個繪制調(diào)用,而最壞的情況下,也僅是跟原先保持相同數(shù)量的繪制調(diào)用而已,不過會消耗更多的內(nèi)存。
作者:何三思
鏈接:https://www.jianshu.com/p/f6dad566746a
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。
轉(zhuǎn)載于:https://www.cnblogs.com/guaishoudashu/p/10491709.html
總結(jié)
以上是生活随笔為你收集整理的在Unity中对森林植被进行优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数字电子钟实验设计(proteus)
- 下一篇: pcie gen3 bios设置_如何设