視錐剔除( Frustum Culling)
攝相機(jī)視野的空間形態(tài)是一個(gè)四棱錐,Unity稱之為“視錐(Frustum)”,默認(rèn)情況下,Unity會(huì)和人的眼睛一樣,自動(dòng)將視錐以外的物體動(dòng)態(tài)地禁止渲染,也就是只渲染視錐以內(nèi)的物體,這就是“視錐剔除”。一般情況下我們是看不到“視錐剔除”現(xiàn)象的,但“視錐剔除”在運(yùn)行時(shí)會(huì)自動(dòng)啟用。
下圖左邊幾條白色線包圍的部分就是相機(jī)視錐(俯視),因?yàn)槲词褂谜趽跆蕹詧?chǎng)景中的所有物體均可見。

下圖為添加遮擋剔除并使用其可視化預(yù)覽功能的情況。在右下角彈出的可視化預(yù)覽面板中,激活“Camera Volumes(相機(jī)體積)”,取消“Occlusion Culling(遮擋剔除)”復(fù)選框的勾選,目的是先禁用遮擋剔除,只預(yù)覽“視錐剔除”效果。說到這里,有些童鞋肯定有些暈,不是說添加了遮擋剔除,怎么又禁用了呢?因?yàn)槭窍胂冉o大家直觀地展示一下視錐剔除的效果,可一般情況下大家是看不到的,而遮擋剔除使用后,視錐剔除和遮擋剔除的效果都可以用可視化預(yù)覽,并且取消預(yù)覽面板中的“Occlusion Culling”復(fù)選,所預(yù)覽到的就只是視錐剔除的效果了。
視錐剔除后,只有視錐以內(nèi)的物體可見,視錐以外的物體都被剔除掉了。對(duì)比上一張圖和下圖右下角游戲視圖的預(yù)覽,我們發(fā)現(xiàn)視錐剔除后,游戲視圖中所看到的內(nèi)容沒有任何變化,這也就是說,視錐剔除不會(huì)改變游戲視圖的視覺內(nèi)容,但是由于剔除了視錐以外的內(nèi)容,游戲視圖相機(jī)的渲染量被大幅降低,如果不剔除,運(yùn)行時(shí)游戲視圖的相機(jī)會(huì)因渲染負(fù)擔(dān)沉重而卡頓。視錐剔除是Unity3d的特性,無需特別設(shè)定,運(yùn)行時(shí)會(huì)自動(dòng)啟用。說到這里,一定有童鞋說,既然這是Unity3d特性,那你費(fèi)什么話,啰里啰嗦說半天視錐剔除?因?yàn)楦闱宄艘曞F剔除的原理,對(duì)于理解遮擋剔除是非常有幫助的。

遮擋剔除(Occlusion culling)
通俗地講,就是將距離相機(jī)當(dāng)前位置最近的一組非透明物體完全遮擋(看不到)的物體,動(dòng)態(tài)地禁用渲染(禁用渲染一些物體,游戲視圖的渲染負(fù)擔(dān)就會(huì)減輕,作品跑起來就會(huì)流暢一些),這就是“遮擋剔除”。簡單地說,就是把被遮擋住的物體剔除掉。
勾選“Occlusion Culling”也就是在Scene視圖中除了預(yù)覽視錐剔除的效果,也預(yù)覽遮擋剔除的效果。勾選后,由下圖可見,剛才視錐內(nèi)保留的好多物體又消失了;使用遮擋剔除后,那些物體也被剔除掉了,所以不可見了;但是對(duì)比游戲視圖的內(nèi)容和前面沒有任何剔除以及視錐剔除后游戲視圖的內(nèi)容,完全一樣,也就是說,遮擋剔除后,也不會(huì)改變游戲視圖的內(nèi)容,但是在視錐剔除的基礎(chǔ)上,又進(jìn)一步大幅度降低了相機(jī)的渲染量,運(yùn)行時(shí)作品會(huì)更加流暢,因?yàn)楸惶蕹矬w的幾何、材質(zhì)、光照貼圖、粒子系統(tǒng)等都不再被渲染了。

通過上面的靜幀圖解,大家對(duì)視錐剔除和遮擋剔除有了形象的理解,但是運(yùn)行時(shí),相機(jī)的位置和方位角是動(dòng)態(tài)變化的,所以被剔除和被保留的物體也是動(dòng)態(tài)變化的。前面為了簡化問題,我用了俯視視角圖解了視錐剔除和遮擋剔除,下面我們用動(dòng)態(tài)GIF圖像來看看實(shí)際遮擋剔除和視錐剔除。

需要說明的是,如果將整個(gè)場(chǎng)景合并為一個(gè)物體,遮擋剔除和視錐剔除沒有任何效果,為什么呢?因?yàn)橐曞F剔除是根據(jù)物體的最大外輪廓(或者說是物體的邊界框)是否在視錐以內(nèi)來確定是否被剔除,如果合并成一個(gè)物體,相機(jī)怎么移動(dòng),物體的邊界框都在視錐以內(nèi)。對(duì)于遮擋剔除來說,都合并成一個(gè)物體了,哪還有被遮擋的物體呢?所以要通過遮擋剔除和視錐剔除優(yōu)化場(chǎng)景,嚴(yán)禁將所有物體合并為一個(gè)物體,除非場(chǎng)景規(guī)模非常小。
遮擋剔除的過程是使用一個(gè)虛擬相機(jī)構(gòu)建潛在可見物體集合的層級(jí)結(jié)構(gòu)數(shù)據(jù),好讓每個(gè)攝像機(jī)在運(yùn)行時(shí)使用這個(gè)數(shù)據(jù)來識(shí)別哪些物體可見,哪些物體不可見。 有了這些數(shù)據(jù),Unity的相機(jī)將只對(duì)可見物體渲染,不僅降低了繪制調(diào)用(draw calls)的次數(shù),并可提高游戲的性能。
遮擋剔除的數(shù)據(jù)由許多單元格(下圖中Scene視圖中的藍(lán)色3d線框)組成,每個(gè)單元格是整個(gè)場(chǎng)景邊界體積的細(xì)分,具體地說就是這些單元格構(gòu)成了一個(gè)二叉樹結(jié)構(gòu)。遮擋剔除使用了兩個(gè)樹結(jié)構(gòu),一個(gè)用于視圖單元(靜態(tài)物體),另一個(gè)用于目標(biāo)單元(動(dòng)態(tài)物體象)。 所有視圖單元映射到定義可見靜態(tài)物體的索引列表,從而為靜態(tài)對(duì)象提供更準(zhǔn)確的剔除效果。

在建模時(shí)要記住很重要的一點(diǎn),即要考慮在物體大小和遮擋剔除的單元格大小之間求得最佳平衡。理想情況下,不應(yīng)該有比物體小太多的單元格,同樣地,也不應(yīng)該讓物體的尺度比單元格大到跨越了許多單元格??梢钥紤]在建模軟件中將大的物體分解成較小的多個(gè)物體來改善剔除,但有時(shí)也需要考慮將小的物體合并在一起以減少繪制調(diào)用(draw calls),并且只要它們都屬于同一個(gè)單元格,就不會(huì)影響遮擋剔除。
遮擋剔除對(duì)模型的要求:要使用遮擋剔除,模型必須在建模軟件中被分解成合理尺寸的大小,以適應(yīng)unity中遮擋剔除的單元格細(xì)分尺寸。在建模軟件中盡可能把模型分解成比較小的幾何體,且被比較大的物體(例如墻壁,建筑物等)遮擋的布局對(duì)于unity中的遮擋剔除優(yōu)化是很有幫助的。
遮擋剔除的一般設(shè)置:在檢視面板中,將要參與遮擋剔除計(jì)算的靜態(tài)物體標(biāo)記為Occluder Static(靜態(tài)遮擋物)或Occludee Static(靜態(tài)被遮擋物),如下圖所示。Occluder是遮擋物,也就是遮擋其他物體的物體,Occludee是被遮擋物,也就是被其他物體遮擋的物體。有的物體需要同時(shí)勾選Occluder Static和Occludee Static,也就是這個(gè)物體既遮擋別的物體,也會(huì)被別的物體遮擋。有的物體只需勾選Occluder Static,例如比較大的物體,它是永遠(yuǎn)不會(huì)被其他物體遮擋。而有的物體只需勾選Occludee Static,例如比較小的物體,因?yàn)樗趽跗渌矬w的可能性很小,單獨(dú)勾選Occluder Static或Occludee Static,可減少遮擋剔除的計(jì)算量,即可加快遮擋剔除的烘焙。如果將場(chǎng)景中比較大且不可能被其他物體遮擋的物體設(shè)置Occludee Static,或者將比較小且不可能遮擋別的物體的物體設(shè)為Occluder Static,除了浪費(fèi)烘焙時(shí)間和增大遮擋剔除數(shù)據(jù)文件外,毫無意義,所以根據(jù)物體的實(shí)際情況,合理地對(duì)其進(jìn)行遮擋剔除設(shè)置,對(duì)加快遮擋剔除烘焙和優(yōu)化遮擋剔除數(shù)據(jù)非常重要。另外補(bǔ)充一點(diǎn),很多人在烘焙場(chǎng)景時(shí),按照官方的要求,將要烘焙的靜態(tài)物體直接設(shè)置為“Static(靜態(tài))“,也就是將檢視面板右上角的“Static”復(fù)選框直接勾選,可當(dāng)展開“Static”后面的下拉菜單的三角符時(shí),發(fā)現(xiàn)后面有一堆這靜態(tài)那靜態(tài)的選項(xiàng),如果直接勾選Static,就等于把這個(gè)下拉菜單里的所有選項(xiàng)(除Noting外)都勾選了,在烘焙場(chǎng)景時(shí),不要直接勾選“Static”,而只需勾選“Lightmap Static”,全部勾上會(huì)給烘焙增加多余的計(jì)算負(fù)擔(dān)和時(shí)間,做什么計(jì)算,就勾什么選項(xiàng),全部勾上,進(jìn)行遮擋剔除計(jì)算時(shí)不分青紅皂白,會(huì)浪費(fèi)很多時(shí)間。

這里特別說明一下,當(dāng)使用LOD Group優(yōu)化時(shí),只有LOD0可作為遮擋物。
設(shè)置物體的Occluder Static和Occludee Static,也可以在遮擋剔除面板中完成,即單擊打開菜單Window > Rendering > Occlusion Culling,在彈出的面板(如下圖所示)中選擇“Object”,并且在場(chǎng)景中選擇“網(wǎng)格渲染器(也就是場(chǎng)景中的物體)”,遮擋剔除面板下方即會(huì)出現(xiàn)Occluder Static和Occludee Static兩個(gè)復(fù)選框,在這里勾選,和前面設(shè)置物體的Occluder Static和Occludee Static屬性異曲同工。遮擋剔除面板各按鈕的功能見下圖。

Occlusion Culling 窗口
1.Object 選項(xiàng)卡

在 Object 選項(xiàng)卡中,可以單擊 All、Renderers 和 Occlusion Areas 按鈕以篩選 Hierarchy 窗口的內(nèi)容。
當(dāng) Renderers 篩選條件激活時(shí),在 Hierarchy 窗口或 Scene 視圖中選擇一個(gè)渲染器,即可在 Occlusion Culling 窗口中查看和更改渲染器的遮擋剔除設(shè)置。
當(dāng) Occlusion Areas 篩選條件激活時(shí),可以在 Hierarchy 窗口或 Scene 視圖中選擇一個(gè)遮擋區(qū)域,然后在 Occlusion Culling 窗口中查看和更改遮擋區(qū)域的 Is View Volume 設(shè)置。也可以單擊 Create New Occlusion Area 以便在場(chǎng)景中創(chuàng)建新的遮擋區(qū)域。
2.Bake 選項(xiàng)卡
在 Bake 選項(xiàng)卡中,可以微調(diào)遮擋剔除烘焙過程的參數(shù)。請(qǐng)通過配置這些設(shè)置在烘焙時(shí)間、運(yùn)行時(shí)數(shù)據(jù)大小和可視化結(jié)果之間找到平衡。
Set Default Parameters 按鈕可將參數(shù)重置為默認(rèn)值。

Smallest Occluder :可以遮擋其他游戲?qū)ο蟮淖钚∮螒驅(qū)ο蟮拇笮。ㄒ悦诪閱挝唬?。通常,要使文件最小且烘焙時(shí)間最短,應(yīng)選擇在場(chǎng)景中產(chǎn)生良好結(jié)果的最大值。
Smallest Hole :攝像機(jī)可以看到的最小間隙的直徑(以米為單位)。通常,要使文件最小且烘焙時(shí)間最短,應(yīng)選擇在場(chǎng)景中產(chǎn)生良好結(jié)果的最大值。
Backface Threshold :如果需要減小烘焙數(shù)據(jù)的大小,Unity 可以在烘焙時(shí)對(duì)場(chǎng)景進(jìn)行采樣,并排除場(chǎng)景中可見遮擋物幾何體所含背面超過給定百分比的部分。背面百分比很高的區(qū)域可能在幾何體的下方或內(nèi)部,因此不太可能是在運(yùn)行時(shí)攝像機(jī)所在的某個(gè)位置。默認(rèn)值 100 表示絕不會(huì)從數(shù)據(jù)中刪除區(qū)域。值越小,產(chǎn)生的文件就越小,但可能會(huì)導(dǎo)致視覺失真。
3.Visualization 選項(xiàng)卡
當(dāng) Visualization 選項(xiàng)卡可見時(shí),如果在 Scene 視圖或 Hierarchy 窗口選擇一個(gè)攝像機(jī),則 Unity 將更新 Scene 視圖,從所選攝像機(jī)的視角顯示遮擋剔除的效果??梢允褂?Scene 視圖中的 Occlusion Culling 彈出窗口來配置可視化設(shè)置。