Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

遮擋剔除

在 3D 渲染引擎中,**遮蔽剔除**是執行隱藏幾何體移除的過程。

在本指南中,我們將學到:

  • 什麼是遮擋剔除的優點缺點。

  • 如何在 Godot 中設定遮擋剔除。

  • 解決 Godot 中控制器的問題

也參考

除了這份說明文件,你可能也會想看看 Godot Demo 專案

遮擋模式

在這個有數百個房間相鄰堆疊的範例場景中,一個動態物件(紅色球體)隱藏在明亮房間的牆後面(在門的左側):

具有遮擋剔除友好佈局的範例場景

具有遮擋剔除友好佈局的範例場景

停用遮擋剔除後,必須渲染照亮房間後方的所有房間。動態物件也必須被渲染:

停用遮擋剔除的範例場景(線框)

遮擋剔除**停用**的範例場景(線框)

啟用遮擋剔除後,只需渲染實際可見的房間。動態物件也被牆壁遮擋,因此不再需要渲染:

啟用遮擋剔除的範例場景(線框)

**啟用**的遮蔽剔除範例場景(線框)

由於引擎要做的工作較少(需要渲染的頂點較少,繪製呼叫也較少),因此只要場景中有足夠的遮擋剔除機會,效能就會提高。這意味著遮擋剔除在室內場景中最有效,最好有許多較小的房間,而不是較少的較大房間。將此與 doc_mesh_lod 和 doc_visibility_ranges 結合起來,可以進一步提高效能效益。

備註

當使用叢集前向渲染後端時,引擎已經執行了*深度預通道*。這包括在渲染場景的實際材質之前渲染場景的僅深度版本。這用於確保每個不透明像素僅著色一次,從而顯著降低過度繪製的成本。

使用 Forward Mobile 渲染後端時可以觀察到最大的效能優勢,因為出於效能原因,它不具有深度預通道。因此,遮蔽剔除將主動減少渲染後端的著色過度繪製。

儘管如此,即使使用深度預通道,複雜 3D 場景中的遮蔽剔除仍然具有明顯的優勢。然而,在遮蔽剔除機會很少的場景中,遮蔽剔除可能不值得增加設定和 CPU 使用率。

遮擋模式

備註

「遮擋物」是指遮擋視線的形狀,而「被遮擋物」是指被隱藏的物體。

在 Godot 中,遮蔽剔除的工作原理是將場景的遮蔽幾何圖形光柵化到 CPU 上的低解析度緩衝區。這是使用軟體光線追蹤庫 Embree 完成的。

然後,引擎使用此低解析度緩衝區來測試遮擋物的 AABB(軸對齊邊界框)與遮擋物形狀。被遮擋物的 AABB(軸對齊邊界框)必須被要剔除的遮擋物形狀「完全遮擋」。

因此,較小的物件比較大的物件更有可能被有效剔除。較大的遮蔽物(例如牆壁)也往往比較小的遮擋物(例如裝飾道具)更有效。

遮擋模式

使用遮蔽剔除的第一步是啟用 渲染 > **遮蔽剔除 > 使用遮蔽剔除 專案設定。 (確保在“專案設定”對話框中啟用“高級”開關才能看到它。)

專案設定會立即應用,無需重啟編輯器。

啟用專案設定後,您仍然需要建立一些遮蔽物。出於性能原因,引擎不會自動使用所有可見幾何體作為遮擋剔除的基礎。相反,引擎需要簡化的場景表示,僅需要烘焙靜態物件。

有兩種方法可以為伺服器匯出專案:

多預留位置

這種方法更適合專門的用例,例如為 MultiMeshInstance3D 設定或 CSG 節點建立遮蔽(由於上述限制)。

啟用上述遮擋剔除專案設定後,將 OcclusionrInstance3D 節點新增至包含 3D 關卡的場景。選擇 OccluderInstance3D 節點,然後選擇要新增至 Occlusionr 屬性中的遮擋器型別:

  • QuadOcclusionr3D(單平面)

  • BoxOcclusionr3D(長方體)

  • SphereOcclusionr3D(球狀遮擋器)

  • PolygonOccluder3D(具有任意數量點的 2D 多邊形)

還有 ArrayOccluder3D,其點無法在編輯器中修改,但可用於從腳本進行程式產生。

遮擋模式

您可以啟用除錯繪製模式來預覽遮擋剔除實際「看到」的內容。在3D 編輯器視窗的左上角,按一下**透視** 按鈕(或**正交**,取決於您目前的相機模式),然後選擇**顯示進階... > 遮擋剔除緩衝區**。這將顯示引擎用於遮蔽剔除的低解析度緩衝區。

在同一選單中,您還可以啟用**查看資訊**和**查看影格時間**來查看右下角的繪製呼叫和渲染像素(頂點+索引)的數量,以及右上角渲染的每秒影格數。

如果在顯示此資訊時在專案設定中切換遮擋剔除,您可以看到遮擋剔除對場景效能的改善程度。請注意,性能優勢在很大程度上取決於 3D 編輯器相機的視角,因為遮擋剔除僅在相機前面存在遮擋物時才有效。

若要在運作時切換遮蔽剔除,請在根視窗上設定“use_occlusion_culling”,如下所示:

get_tree().root.use_occlusion_culling = true

在運作時切換遮擋剔除對於比較正在運作的專案的效能很有用。

效能

在建構關卡時考慮遮擋

這就是很多專業人士的秘密。好的關卡設計並不只是滿足遊戲性的需求,也應該同時考慮遮擋。

對於室內環境,新增不透明的牆壁以定期“打破”視線,並確保一次不會看到太多場景。

對於大型開放場景,請盡可能使用類似金字塔的結構來確定地形的標高。與任何其他地形形狀相比,這提供了最大的剔除機會。

避免在遊戲過程中移動 OcclusionInstance3D 節點

這包括移動 OccluderInstance3D 節點的父節點,因為這將導致節點本身在全域空間中移動,因此需要重建 BVH(邊界體積層次結構)。

切換 OccluderInstance3D 的可見性(或其父級之一的可見性)並不那麼昂貴,因為更新只需要發生一次(而不是連續發生)。

例如,如果您有一扇滑動門或旋轉門,則可以使 OccluderInstance3D 節點不是門本身的子節點(以便遮擋器永遠不會移動),但您可以在門開始打開後隱藏 OccluderInstance3D 可見性。一旦門完全關閉,您就可以重新顯示 OcclusionrInstance3D。

如果您絕對必須在遊戲過程中移動 OcclusionrInstance3D 節點,請為其使用原始 Occlusionr3D 形狀,而不是複雜的烘焙形狀。

使用盡可能簡單的遮擋物形狀

如果您發現複雜 3D 場景中效能低或卡頓,則可能表示 CPU因渲染詳細遮蔽物而過載。選擇 OccluderInstance3D 節點,增加 Bake > Simplification 屬性,然後再次烘焙遮蔽物。

請記得保持簡化值合理。對於關卡幾何形狀來說太高的值可能會導致發生不正確的遮蔽剔除,如 我的被遮蔽者在不該被剔除的情況下被剔除 所示。

如果這仍然沒有導致足夠低的 CPU 使用率,您可以嘗試調整 渲染 > 遮擋剔除 > BVH 建構品質 專案設定和/或減少 渲染 > 遮擋剔除 > 每線程遮擋光線。您需要在「專案設定」對話方塊中啟用「進階」開關才能查看這些設定。

疑難排解

我的被遮蔽者在該被剔除的時候卻沒有被剔除

在遮擋器一側:

首先,仔細檢查 OccluderInstance3D 中的 Bake > Cull Mask 屬性是否設定為允許烘焙您想要的網格。 MeshInstance3D 節點的可見性層必須存在於剔除遮罩中,網格才能包含在烘焙中。

另請注意,遮擋器烘焙僅考慮具有“不透明”材質的網格。表面將*透明*材質將**不**包含在烘焙中,即使應用在其上的紋理是完全不透明的。

最後,請記住,烘焙遮擋物時**不**考慮 MultiMeshInstance3D、GPUParticles3D、CPUParticles3D 和 CSG 節點。作為解決方法,您可以手動為這些節點新增 OccluderInstance3D 節點。

在被遮蔽方:

確保**額外剔除餘裕**設定為盡可能低(通常應為``0.0``),並且在物件的 GeometryInstance3D 部分中停用**忽略遮蔽剔除**。

另外,檢查 AABB 的大小(選擇節點時以橘色框表示)。此軸對齊的邊界框必須被遮擋物形狀*完全*遮擋,才能隱藏被遮擋物。

我的被遮蔽者在不該被剔除的情況下被剔除

造成這種情況的最可能的原因是,遮擋物烘焙中包含的物件在烘焙遮擋物後已被移動。例如,當行動關卡幾何圖形或重新排列其佈局時,可能會發生這種情況。要解決此問題,請選擇 OccluderInstance3D 節點並再次烘焙遮擋物。

這種情況也可能發生,因為動態物件包含在烘焙中,儘管它們不應該包含在內。使用遮蔽剔除除錯繪製模式 <doc_occlusion_culling_preview>` 尋找不應出現的遮蔽形狀,然後相應調整烘焙剔除蒙版 <doc_occlusion_culling_baking>`。

最後一個可能的原因是在遮擋器烘焙過程中過於激進的網格簡化。選擇 OccluderInstance3D 節點,減少 Bake > Simplification 屬性,然後再次烘焙遮蔽物。

作為最後的手段,您可以啟用被遮蔽者的 忽略遮蔽剔除 屬性。這將抵消該物件的遮蔽剔除的效能改進,但對於永遠不會被剔除的物件(例如第一人稱視圖模型)執行此操作是有意義的。