所有文章
教學 · 6 min read

沒有幀率懸崖的密林:LOD、假身與實例化

如何在幀率下渲染成千上萬棵樹——從完整網格到廣告牌的 LOD 鏈、任何角度都撐得住的八面體假身、實例化與剔除,以及讓烘焙好的森林不顯得死氣沉沉的風與著色技巧。

Spruce forest on a green alpine slope with a handful of wooden cabins below

簡而言之: 一片令人信服的密林是一場效能 boss 戰——成千上萬棵高多邊形樹、層疊的透明度,以及一路延伸到地平線的實例。你靠一 條以假身(面向相機的廣告牌,從任何角度偽裝成 3D 樹)收尾的、有紀律的 LOD 鏈,激進的實例化與剔除,以及幾個著色小把戲來讓廉價 的遠景樹不會自我暴露,來贏下它。本文走完從完整網格到廣告牌的整條鏈、八面體假身的把戲,以及如何讓一片重度優化的森林不顯得死 氣沉沉。

森林邊緣,樹木退向縱深 這裡的每棵樹離相機的距離都不同,所以每棵樹的成本都該不同。廉價森林的藝術,是只把多邊形花在近處的那些身上,其餘的都用可信的方 式偽裝。

核心思路:按距離付費

5 公尺外的一棵樹和 500 公尺外的一棵樹不該花同樣的錢。一條 LOD 鏈在近處花全細節,隨距離漸次採用更廉價的表示,最終止於 一塊平坦的廣告牌——因此總成本在森林增長時保持平坦。

整場遊戲就是拒絕為相機幾乎解析不到的樹支付全價。近處,一棵樹是帶獨立葉片卡的完整網格;遠處,它就是一小把像素,一張平坦的圖 片就能完美再現。一條 LOD(細節層次)鏈把這形式化:同一棵樹的若干版本,成本遞減,按螢幕大小切換。這樣,一片一萬棵樹的森林, 所花的成本大致等於細節可見的那部分,而非把每棵樹按全品質加起來。沒有它,密度會把你的幀時間線性打入地面;有了它,你能用同 樣的預算把樹的數量往上推得遠得多。

LOD 鏈,逐級過一遍

LOD0 帶葉片卡的完整網格(近);LOD1–2 削減幾何與簡化的葉片(中);LOD3 少數幾張卡或單張卡;最終 LOD 是一張假身/ 廣告牌(遠)。每一檔大約把成本減半,而切換保持不可見。

一條典型的植被 LOD 鏈大致跑成這樣:LOD0,帶所有葉片卡的完整細節網格,用於緊挨著玩家的樹;LOD1–LOD2,削減的樹幹幾何 與更少、更大的葉片卡,用於中景;LOD3,一個被極度簡化的卡片集合;以及一張最終假身——本質上是一張平坦圖片——用於所有遠 方。手藝在於過渡距離與融合,好讓切換不彈跳。抖動或交叉淡入的 LOD 過渡把切換藏起來;在錯誤距離上的一次硬彈跳,就是那句打 破幻覺的破綻。按你實際的相機去調這些距離,而不是預設值。

假身:從任何角度偽裝 3D

一張假身(八面體假身)把樹從數十個角度預算圖進一張圖集,再把最接近當前視角的那次採集當作廣告牌顯示。不像一張平坦 的廣告牌,它在相機繞行時也看起來對——廉價,但 3D 味十足。

鏈的遠端是最大節省所住之處,而假身就是讓它們能被接受的那個聰明把戲。一張樸素的廣告牌——一張轉向相機的平坦圖——正面看還行, 可你一移動它就變平並不自然地滑動。而一張八面體假身是這樣解決的:把樹從圍繞一個球體排布的許多視點做預算圖,把它們打包進 一張紋理圖集,然後顯示與當前相機方向最接近的那次採集角度(在最近的幾張之間融合)。結果就是以一小部分成本,從任何角度都讀作 一棵真正的 3D 樹,這就是為什麼假身是可信遠景森林的脊梁。它們烘焙一次,繪製時幾乎不花錢。

蕨類與低矮下層灌木鋪滿森林地面 地表層能迅速把實例數放大。下層需要與樹同樣的紀律:把它實例化、給它 LOD、狠狠剔除它——80 公尺之外的一株蕨根本不該在繪。

實例化與剔除

把重複的樹以實例形式繪製,好讓幾千棵只花幾個繪製呼叫;並激進地剔除——視錐剔除畫面外的東西,距離剔除小東西。實例化 修好 CPU 成本;剔除阻止你為不可見的東西付錢。

即便 LOD 完美,把一萬棵樹作為單獨物件提交也會把 CPU 埋掉。實例化把一棵樹的所有拷貝坍縮成幾次繪製呼叫,這一點對一片真正的森 林沒得商量——而這正是把散佈烘焙成引擎原生實例所給你的。除此之外,狠狠剔除:視錐剔除丟掉視野之外的一切,距離剔除移除超出某個 範圍就小到看不見的地表雜物與細小植被。特別是草與下層,應當有硬的、近的剔除距離,因為它們把實例數放大得比樹還快。一套先繪密 度、再烘焙成實例化網格的工作流——就像 Numivo 那樣——正好把一片密林所需的、成批且可剔除的形態交給引擎。

讓廉價森林活下去

重度優化會讓森林看起來靜態而無生氣——用近處 LOD 上一點點風、實例之間的顏色與比例變化,以及不讓遠處假身讀作平面紙 板的著色去反制它。

這一切效率的風險就是一片跑得飛快卻毫無生氣的森林。三處便宜的收筆把它拉回來:——在近處 LOD 上做頂點動畫,讓近景植被動 起來,即便遠處的假身保持靜止(沒人會注意 300 公尺外一棵靜止不動的樹)。變化——按實例隨機化比例、旋轉與色調,好讓眼睛抓不 到重複;一模一樣的樹是複製貼上的破綻。以及在假身上的著色用心——把它們的光照烘進去,別在太陽角度改變時被壓平成明顯的紙 板。把你省下的幀時間花在近景這些細節上,那正是玩家真的會看的地方,這樣這片被優化過的森林會和未優化的一樣有生命感——而且跑 起來快好幾倍。

值得偷的現場數字

  • 成本原則:按距離付費——遠處的樹不能像近處的那樣花錢
  • LOD 鏈:完整網格 → 削減 → 卡片集合 → 假身,每檔大約把成本減半
  • 假身 = 圖集裡預算圖的角度→從任何視角看都 3D 味十足的廣告牌
  • 把重複的實例化(幾次繪製呼叫)+ 把小的遠景植被狠狠剔除
  • 讓它活著:近處 LOD 的風 + 每實例變化 + 烘好的假身著色

迷你問答

廣告牌 vs 假身——差在哪? 廣告牌是一張面向相機的平坦圖,你繞它轉動時它會變平。假身存了很多個角度並顯示對的那一個,所以 它在 3D 裡撐得住。任何玩家會繞著走或從旁走過的東西,都用假身;樸素的廣告牌只適合真正遙遠、靜止的背景板。

一棵樹需要多少檔 LOD? 通常三到四檔再加一張假身。更多並不自動等於更好——每檔都有製作與記憶體成本。目標是讓每次切換都是一 小步、不被察覺,而不是一個上限。

Nanite 是否讓這些過時? 它改變了幾何這一側——Nanite 處理密集的網格細節而無需傳統 LOD——但透明度(葉片卡)、實例化紀律與 剔除仍然要緊,假身在遠景仍有用武之地。原則活下來了;工具在挪位。

最常殺掉森林效能的是什麼? 相互重疊的透明葉片卡帶來的過繪製,以及未剔除的地表植被。收緊葉片卡、把下層近處剔除掉、把一 切都實例化——這三樣在你還沒碰到樹的網格之前,就能把預算大頭奪回來。

一片密林是最懲罰性的渲染對象之一,也是把它做對最有回報的對象之一。建好 LOD 鏈,讓假身扛下遠景,無情地實例化並剔除,把節省 出來的花在近處的風與變化上——你就會擁有一片一路延伸到地平線守得住幀率的森林。