UE5 中 3DGS 場景的幀率調優
第一步:定位瓶頸
調參之前必須先確認幀率下降是不是 3DGS 造成的。場景裏的光照、陰影、後處理、常規模型、藍圖邏輯都可能是真正的瓶頸,此時無論怎麼調 LCC 參數都不會有改善。
先確認瓶頸來自 3DGS
把場景中除 3DGS 以外的元素隱藏或移除,對比幀率變化:
- 記錄當前幀率作為基準(
stat fps或stat unit)。 - 隱藏 LCC Actor,只留場景其餘部分,記錄幀率。
- 反過來只留 LCC Actor,隱藏或移除其他模型、光源、後處理體積、UI,記錄幀率。
原場景裏元素較多、不便逐個隱藏時,更乾淨的做法是新建一個空白關卡,只放一個 LCC Actor 加載同一份數據,在相同視角下記錄幀率。這樣排除了原場景的全部干擾,得到的就是 3DGS 自身的性能基線。
對比三組數據:
| 結果 | 結論 |
|---|---|
| 只留 LCC 時幀率仍然低 | 瓶頸在 3DGS,繼續本篇後續步驟 |
| 隱藏 LCC 後幀率沒有明顯回升 | 瓶頸在場景其他部分,應先優化那部分 |
| 兩者單獨都正常,同時存在才低 | 總量超出硬件預算,兩邊都要壓,或降低分辨率 |
先排除引擎默認場景元素
新建關卡時引擎會自帶一批默認 Actor,其中有幾項開銷不小,容易被誤當成 3DGS 的成本。最典型的是 VolumetricCloud(體積雲):它逐幀做體積光線步進,即使畫面裏只露出一小片天空也持續消耗 GPU。
項目不需要天空效果時,直接從關卡裏刪除以下 Actor:
| Actor | 說明 |
|---|---|
| VolumetricCloud | 體積雲,GPU 開銷顯著,純 3DGS 場景通常用不到 |
| ExponentialHeightFog | 高度霧,與 3DGS 疊加後還會影響觀感 |
| SkyAtmosphere | 大氣散射,僅在需要天空時保留 |
3DGS 數據本身通常已包含環境信息,這些效果多數情況下不需要。刪除後重新測幀率,再判斷是否還需要調 LCC 參數。
測試時固定條件,否則數據無法比較:同一地圖與出生點、同一攝像機位置或路徑、同一分辨率與 Screen Percentage,Lumen、虛擬陰影貼圖、後處理、SceneCapture 的開關狀態保持一致。先跑一遍預熱再記錄,不要把首次 Shader 編譯和首次磁盤讀取混進穩定幀率。每次只改一類設置。
常用的觀測命令:
stat fps // 幀率
stat unit // Frame / Game / Draw / GPU 四項幀時間
stat gpu // GPU Pass 細分
stat rhi // 繪製調用、圖元、顯存
ProfileGPU // 單幀 GPU Pass 明細
確認是 3DGS 後再用 LCC 統計
Actor 面板 Actions > Stats 可打開統計面板,也可在控制台輸入 stat xgrids。

使用 stat xgrids 查看 LCC 實時性能統計
參數詳細信息請查看性能優化參數說明:統計數據
重點看 Current Render Main Splats 與 Current Render Nodes:多數性能問題的直接原因就是同屏渲染點數過多。
同時打開 LOD 可視化
看統計數字的同時,用 Actor 面板 Actions > Debug Node Bound 打開節點 Level 可視化,直觀確認當前視角的 LOD 分佈。顏色越暖表示 Level 越低、細節越高。
優化的思路是在觀感可接受的前提下儘可能減少同屏點數,重點看 Level 0 鋪得有多遠:
- 畫面中暖色區域延伸到多遠?這個距離上是否真的需要最高精度的數據?
- 把切換到更粗層級的距離提前,畫面觀感有沒有可感知的下降?
多數場景裏 Level 0 的作用距離都比實際需要的遠,讓它更早切換到粗層級,點數下降立竿見影,這是所有手段中收益最明顯的一項。確認有壓縮空間後進入第二步調 Level Factor。
第二步:調整 LOD
這是收益最明顯的一步。多數場景裏 Level 0 的作用距離都遠超實際需要,讓它更早切換到粗層級,同屏點數會立刻下降,而觀感往往沒有可感知的變化。先做這一步,再考慮後續手段。
LOD 有三個獨立旋鈕(Level Factor、Start Level、End Level)

配置 Level Factor、Start Level 與 End Level
2.1 先確定 Level Factor 的作用方式
兩條管線選擇 Level 的機制不同,Level Factor 的作用方式也不同,但方向一致:值越大,節點越早切換到低細節層級。
| 管線 | Level 判定依據 | Level Factor 的作用 |
|---|---|---|
| LCC | 全局 RangeForLevel 距離表 | 把距離表整體除以該值 |
| LCC2 | 屏幕空間誤差(SSE) | 把算出的 SSE 除以該值,誤差變小則不再細化 |
LCC2 管線:屏幕空間誤差
LCC2 不使用 RangeForLevel,而是為每個節點計算屏幕空間誤差:節點自身的幾何誤差投影到屏幕上佔多少像素。誤差超過閾值就細化到更精細的子節點,否則停在當前層級。
這個誤差同時受節點距離、視野角度與屏幕分辨率影響,因此同一個 Level Factor 在不同分辨率或 FOV 下的實際切換距離並不相同。這也意味着 LCC2 的 LOD 分佈無法用一張距離表預先算出,只能用 2.5 的 Debug Node Bound 實際觀察。
調參方式與 LCC 管線一致,直接看 2.2 的測試階梯。
LCC 管線:距離表
Level Factor 的作用是把全局 RangeForLevel 數組除以該值。值越大,每個 Level 的作用距離越短,節點越早進入低細節層。
RangeForLevel 默認值(11 項,ProjectSettings > Plugins > LCC4Unreal > Level):
Level: 0 1 2 3 4 5 6 7 8 9 10
米: 15 50 80 110 140 170 190 220 250 280 350
除以 Level Factor 後的實際作用距離(單位:米,非整數按四捨五入顯示):
| Level Factor | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1.0(默認) | 15 | 50 | 80 | 110 | 140 | 170 | 190 | 220 | 250 | 280 | 350 |
| 1.25 | 12 | 40 | 64 | 88 | 112 | 136 | 152 | 176 | 200 | 224 | 280 |
| 1.5 | 10 | 33 | 53 | 73 | 93 | 113 | 127 | 147 | 167 | 187 | 233 |
| 2.0 | 7.5 | 25 | 40 | 55 | 70 | 85 | 95 | 110 | 125 | 140 | 175 |
怎麼用這張表:Level Factor = 2 時,原來 15 米內使用最高細節,現在只有 7.5 米內使用最高細節。這比「降低一半細節」的說法精確得多——它改變的是每個 Level 的作用距離,不是點數比例。
Level 與距離的確切比較方式(取上界還是下界、開區間還是閉區間)屬於內部實現,上表用於估算調參幅度,實際 Level 分佈請用 2.5 的 Debug Node Bound 確認。這張表只適用於 LCC 管線。
距離超過 RangeForLevel 最後一項時,節點直接使用自身可用的最粗 Level,不存在找不到層級的情況。因此把 Max Distance 提高到超過 350 米不需要同步調整這張表。

在項目設置中配置 Range For Level 距離數組
2.2 Level Factor
取值與默認值見性能優化參數說明:Level Factor
這是 LOD 裏首選的旋鈕,因為它是漸進的,不會一次性砍掉整個細節層級。
測試階梯:
1.0 → 1.25 → 1.5 → 2.0
優先檢查:輪廓、細線、小物體、地面細節、Level 切換過渡區。這些位置最先暴露細節不足和 LOD 跳變。

調整 Level Factor 後的 LOD 變化
2.3 Start Level(起始等級)
取值與默認值見性能優化參數說明:Start Level
提高它會直接跳過編號最低(最精細)的 Level:
0 → 1 → 2
這比輕微調整 Level Factor 激進得多——它是整層丟棄,不是距離縮放。只在兩個條件同時滿足時使用:stat xgrids 顯示 Level0 Splats 確實是主要成本,且近景畫質允許變粗。近景明顯發糊時應退回 0。

提高 Start Level 後跳過高細節層級的效果
2.4 End Level(一般不動)
取值與默認值見性能優化參數說明:End Level
降低它會限制可使用的最粗層級:即使數據裏有更粗的層級也不會被使用,遠處只能停留在 End Level 這一級,渲染點數反而比需要的更多。它不是提速按鈕,除非已經理解數據的 Level 結構,保持默認值。
設置時必須滿足 Start Level <= End Level,Setter 不會替你校驗。

調整 End Level 後限制低細節層級的效果
2.5 用 Debug Node Bound 驗證
Actor 面板 Actions > Debug Node Bound 可視化節點邊界與 Level。顏色序列為紅、橙、黃、綠、藍、紫,紅色為最低 Level(最高細節),白色代表最高 Level(最低細節)。
改完 LOD 參數後用它檢查:近景是否仍是紅/橙色(高細節),遠景是否順暢過渡到冷色,有沒有出現同一距離上 Level 反覆跳變的區域。

使用 Debug Node Bound 檢查 LOD 分佈
LOD 的驗證要點
- 節點數與 Splat 數是否下降;
- 近景有沒有過早變粗;
- 相機移動時有沒有明顯的 LOD 跳變;
第三步:最大渲染距離
取值與默認值見性能優化參數說明:Max Distance(m)

設置 Max Distance 最大渲染距離
它和 LOD 的區別
Max Distance 直接砍掉超出距離的數據,減少的是可渲染的空間範圍;LOD 是在範圍內降低精度。兩者互補:LOD 調完仍有壓力時,用它進一步收緊範圍。
它可能同時減少候選節點和後續的遍歷、加載、上傳、排序、填充工作,但具體減少多少屬於實現與數據相關行為,必須根據實際統計驗證,不能假定固定的收益比例。
先勾內聯開關,否則改了不生效
Performance 分類下每個參數左側都有一個勾選框。不勾選時文本框裏的數值不起作用,運行時使用插件內置默認值。調整沒有效果時先檢查這裏。
距離的調節步驟
- 站在場景中最遠需要看到模型數據的位置,測量實際需要的距離。
- 勾選參數左側的開關。
- 設為「實際最大可見距離 + 必要餘量」。
- 按階梯逐步收緊,不要一次降到極低:
300 m(默認)→ 225 m → 150 m → 按項目實際距離細調
上面是測試階梯,不是推薦值。室內、街區、大場景、飛行視角的合理值差異很大,必須按項目實測。

調整 Max Distance 後的渲染範圍變化
距離的驗證要點
Current Render Nodes、Current Render Splats是否下降;- GPU ms 或 Traversal Time 是否下降;
- 走到距離邊界時有沒有出現內容突然消失;
- 快速移動時是否更容易看到未加載區域;
第四步:設置點數硬上限
取值與默認值見性能優化參數說明:Max Splat Num
Max Distance 控制的是空間範圍,但同一範圍內的數據密度可能差異巨大。Max Splat Num 提供一道單幀工作量上限,防止走進高密度區域時點數突然飆升。它與 LOD、距離是互補關係,不能互相替代。
注意過大的值會被自動限制到 GPU 單幀可渲染的量,把面板值拉到上限並不能突破硬件能力,只是讓這道上限形同失效。要讓它真正起作用,必須設成低於當前視角實際點數的值。

設置 Max Splat Num 單幀點數上限
點數上限的調節步驟
- 勾選參數左側的開關。
- 從默認值開始按比例下調,單位是萬:
3000 → 2250 → 1500 → 1000
- 每次下調後,去高密度區域觀察,不要只看空曠區域。

調整 Max Splat Num 後的點數與畫面變化
點數上限的驗證要點
- GPU ms 與
Current Render Splats是否隨上限同步下降; - 有沒有出現局部變稀、閃爍、透明結構斷裂。
如果降低上限後點數和 GPU ms 都沒變化,說明當前視角根本沒有達到該上限,這一項不是當前瓶頸——回到第一步重新定位。
第五步:降低像素填充成本
5.1 SplatScale
參數詳情見畫面調節:SplatScale
減小它會降低單個 Splat 的屏幕覆蓋面積,從而減少透明疊加。
做法:從當前畫質值小步下降,在高分辨率、近景和物體輪廓處檢查。降得過多會讓表面出現孔洞或明顯變薄。

調整 SplatScale 降低高斯點屏幕覆蓋面積
5.2 Small Splat Threshold (px)【僅 LCC2 管線】
可用 CVar 即時測試,不必重啟:
r.LCC2.SmallSplatThreshold 0
r.LCC2.SmallSplatThreshold 0.5
r.LCC2.SmallSplatThreshold 1
值越高潛在收益越大,遠景顆粒感也越明顯。只在 GPU 或 SH 計算確實是瓶頸時才繼續提高;數據本身沒有 SH時,跳過 SH 帶來的收益有限。

設置 Small Splat Threshold 像素閾值
5.3 Quad Extent Threshold【僅 LCC2 管線】
增大該值產生更緊的 Quad,減少 overdraw,但可能裁掉半透明邊緣。
r.LCC2.QuadExtentThreshold 0.006 → 0.008 → 0.01
出現輪廓變硬、邊緣缺失、Splat 形狀異常時回退。

設置 Quad Extent Threshold 控制 Splat Quad 範圍
5.4 Frustum Cull Margin【僅 LCC2 管線】
取值與默認值見性能優化參數說明:Frustum Cull Margin
它控制的是裁剪餘量,不是點數上限。
只有在屏幕邊緣沒有彈出的前提下,才嘗試向 1.0 小步降低:
r.LCC2.FrustumMargin 1.2 → 1.1 → 1.0
快速轉動相機時如果邊緣出現內容閃進閃出,說明降過頭了。

設置 Frustum Cull Margin 視錐裁剪邊距
5.5 抗鋸齒
抗鋸齒的 GPU 成本不低,TSR 尤其明顯。場景中只有 3DGS、沒有常規網格與 UI 時,把對應設置改為 None 通常畫質損失很小而幀率收益可觀。
各管線的默認方法與取捨見性能優化參數說明:抗鋸齒方法。

配置不同 LCC 管線的抗鋸齒方法
第六步:關閉不需要的功能
這一步收益明確但都有功能代價,逐項確認項目是否真的不需要,而不是一律關掉。
| 功能 | 適用管線 | 何時可關 | 副作用 |
|---|---|---|---|
ReceiveShadows | 僅 LCC | 不需要接收陰影 | 失去接收陰影效果 |
LightMode = Lit | 通用 | 數據自身顏色已滿足觀感,或不需要場景燈光 | 場景燈光不再影響 LCC |
UseShcoef | 通用 | 只需基礎顏色且觀感可接受 | 失去視角相關的顏色變化 |
SingleLayerWater Support | 僅 LCC2 | 不使用單層水 | 3DGS 無法正確參與水體遮擋與折射 |
EnableCollision | 通用 | 場景不需要碰撞 | 沒有碰撞效果,不能生成導航區域 |
第七步:排序與顯存
透明排序和顯存管理按管線分開處理:Sort Factor 與額外預加載只在 LCC1 上有,GPU 顯存預算只在 LCC2 上有。
7.1 Sort Factor【僅 LCC 管線】
取值與默認值見性能優化參數說明:Sort Factor
它作用於全局 SortFrequencyForLevel 表,控制各 Level 的節點多久重新排序一次。值越大排序次數越少、性能越好,但相機或節點變化後透明順序更新更慢,可能出現短暫的穿插錯誤。

設置 Sort Factor 調整 LCCActor 排序頻率

配置各 LOD 層級的 Sort Frequency
7.2 額外預加載節點【僅 LCC 管線】
它的作用是緩解快速旋轉時屏幕邊緣的空洞,代價是增加節點工作量。
這一項有兩層狀態,容易搞錯:
- 不勾選左側開關時,回退到內部默認值,有效結果仍是開啟;
- 要真正關閉,必須先勾選開關,再把值設為關閉。
只有當統計顯示節點數和預加載確實是明顯負擔、且項目能接受快速轉向時的邊緣空洞,才關閉它。關閉後出現空洞就恢復——不要用增加線程數掩蓋數據沒準備好的問題。

配置額外預加載節點以緩解快速轉向空洞
7.3 LCC2 GPU Memory Budget【僅 LCC2 管線】

設置 LCC2 GPU Memory Budget 顯存預算
它只統計單個 LCC2 模型的位置、顏色和球諧數據。提高預算只在以下情況可能有幫助:
- GPU 仍有足夠空閒顯存;
- 卡頓主要發生在移動到新區域或多視口工作時。
它不會減少 Splat 數、排序量或像素覆蓋。沒有驅逐或碎片問題時,提高預算只會增加常駐顯存而不提高幀率。
調節步驟:
- 先記錄整機顯存峰值,不只看 LCC 預算。
- 從默認值開始,按 1024 MB 階梯增加。
- 每次修改後重啟引擎。
- 複測最重視角、全部 SceneCapture / nDisplay 視圖和長時間運行。
- 給 UE 場景紋理、Render Target、Nanite、Lumen、VSM、排序緩衝和操作系統留出顯存。
不要在沒有完整顯存監控時直接設為 8192 MB。
日誌還會打印顯存佔用分解,可用於核對預算是否合理:
GPU footprint: %u slots (%s), %.2f MB total - gaussian %.2f, SH %.2f, sort %.2f (1 view), other %.2f MB
其中 sort 項即排序緩衝,日誌按 1 個視圖計算,多視口需按視圖數換算。
第八步:加載 線程 內存
8.1 不要先加線程【僅 LCC 管線】
取值與默認值見性能優化參數說明:線程池設置
增加線程可能提高 CPU 併發,也可能增加線程競爭、上下文切換、瞬時磁盤壓力和上傳峰值。Exporter 線程與運行時渲染無直接關係,調它不會改善幀率。
判定條件:只有當統計顯示對應隊列積壓、同時 CPU 仍有可用核心時,才每次小幅增加 2~4 個線程並複測。CPU 已經滿載時應該減少工作量,而不是繼續加線程。
如果 Create Thread 這一項持續出現耗時,說明線程池在反覆擴容,此時應調整預創建數量而不是上限。
8.2 Splat Number For Discard Per Node【僅 LCC 管線】

設置每個節點的稀疏 Splat 丟棄閾值
它的意圖是忽略極稀疏的節點——某些數據裏存在大量只含一兩個 Splat 的節點,管理這些節點的開銷超過了它們的畫面貢獻。
提高它可能減少低密度節點的管理成本,也可能刪掉孤立細節。請在細線、樹枝、欄杆、遠處小物體處檢查,不能只看整體幀率。改完記得重新加載數據,否則看到的還是舊結果。
8.3 內存與顯存釋放閾值

配置 CPU 與 GPU 內存佔用和釋放閾值
四項閾值的取值與默認值見性能優化參數說明:Usage 分類
這是內存壓力下的釋放策略,不是常規提幀旋鈕:
- 閾值過低或釋放比例過大 → 可能造成「釋放—重新加載—再次釋放」的抖動;
- 閾值過高 → 可能推遲釋放,增加系統內存 / 顯存壓力;
- 只有通過長時間測試確認存在內存壓力或反覆驅逐時才調整。
判斷依據是 CPU Occupy Percentage / GPU Occupy Percentage 與對應閾值的關係,以及 Released CPU Node Num / Released GPU Node Num 是否持續增長。截圖中顯存佔用 86% 已超過 80% 閾值、顯存側釋放數達 1943,就是典型的顯存壓力信號。
第九步:多視口 碰撞 水體
9.1 多相機與 SceneCapture
每增加一個實際參與渲染的視圖,都可能增加遍歷、渲染或排序工作;LCC2 還會按視圖增加排序緩衝。
逐項檢查:
- 是否存在未使用但仍每幀更新的 SceneCapture;
- Render Target 分辨率是否過高;
- 更新頻率是否必須每幀;
ShowOnlyActors是否只包含需要的內容;- 小地圖能否改用
PointCloud或更低分辨率; - nDisplay、分屏、MRQ 是否同時創建了額外視圖。
用 stat xgrids 的 Camera Num(Render) 確認實際參與渲染的視圖數是否與預期一致;Camera Num 是參與更新的相機數,兩者可能不同。數值高於預期時,說明有視圖在你不知情的情況下參與了渲染。
完全不用 SceneCapture 時可關閉 SceneCaptureComponent Support,詳見性能優化參數說明。

配置 SceneCaptureComponent Support 多視口支持
9.2 遍歷模式

選擇 Frustum 或 Circle 默認遍歷模式
Circle 適合需要周圍方向數據的環幕、nDisplay、360 全景;Frustum 是單視口的默認基線。
普通單相機項目不要為了「防止任何方向缺塊」默認切到 Circle——它會把相機周圍整個圓形範圍都納入遍歷,而視錐模式只處理看得見的那一部分。如果工作流必須用 Circle,應同步收緊 Max Distance、點數上限和多視口分辨率。
LCC2 管線不需要調整這一項,保持 Frustum 即可。
9.3 碰撞與導航
碰撞關閉時,不需要為碰撞距離調參。啟用後,碰撞讀取、異步物理烘焙和 NavMesh 更新可能增加 CPU、內存和卡頓——注意這類成本不一定體現在 FPS 上,需要單獨看碰撞相關的統計項。
碰撞距離的取值與默認值見性能優化參數說明:Max Load Collision Distance(m)
- 純展示項目直接關閉碰撞。
- 需要碰撞時,勾選參數左側開關,把
Max Load Collision Distance(m)設為實際交互範圍。

設置 Max Load Collision Distance 碰撞加載距離

調整碰撞加載距離後的動態碰撞範圍變化
- 不要把渲染距離和碰撞距離機械設成相同值。遠景可見不代表遠處需要物理碰撞。
- 縮小碰撞距離會直接限制玩家交互與 AI 可用範圍,改完必須做功能回歸,不能只看幀率。
使用導航時策略相反,碰撞距離要儘可能覆蓋玩家可到達的全部區域,讓這些區域的碰撞一次性加載完成。碰撞是分塊動態加載的,運行中新的碰撞塊換入會觸發導航數據重新構建,造成明顯卡頓。
配套要點:
NavMeshBoundsVolume覆蓋玩家活動範圍,並確認該範圍內的碰撞都已加載- 儘量使用 Static 烘焙,避免 Dynamic 動態烘焙——後者會在碰撞變化時持續重建
9.4 單層水【僅 LCC2 管線】
功能說明與完整配置見單層水支持,本節只講性能取捨。
SingleLayerWater Support 在項目設置中是全局項,但其實現依賴 LCC2 的中值深度,因此對 LCC 管線的 Actor 不生效。
- 不使用單層水時保持關閉;
- 啟用後必須重啟才生效;
- 代價是水面像素會損失虛擬陰影貼圖的陰影質量,這是功能取捨而非純性能取捨;
- 只有在 3DGS 被單層水材質錯誤遮擋時才需要開啟。