基於 Unity 引擎的遊戲開發進階之 全局光照

Unity 全局光照

在介紹全局光照之前需先理解局部光照。

計算機圖形學的光照模型,是指渲染程序在計算三維場景物體表面光照效果時所採用的計算規則。 光照模型可以分為局部光照模型和全局光照模型兩類。採用局部光照模型,引擎在計算光照時,不考慮物體之間的光照的相互影響,孤立地看待每一個物體。 計算光照過程中,每次只考慮一個光源,一個物體表面,和一個觀察者,三者之間的相互作用。局部光照模型具有計算方法簡單,速度快,資源消耗少等優點,是遊戲中最常使用的光照模型。 採用局部光照模型製作的遊戲,視覺效果一般,遊戲畫面與真實世界有較大的差距。

全局光照(Global Illumination)

簡稱 GI。 是計算機圖形學中複雜的光照計算方法,在計算物體光照時,需要考慮光源直接照射到物體表面所產生的影響,也要考慮間接光照,也就是說物體之間的反射光線和折射光線所產生的影響。真實世界中,間接光照無處不在。比如,太陽光通過窗戶直接照射室內,只能直接照亮窗前的一小塊區域。但是,整個房間都是明亮的,原因在於房間中的地面、 牆壁和其他物體都會反射光線,這些間接的反射光線照亮了整個房間。 又比如燈光照射到一個紅色的沙發表面,沙發表面的反射光線,會使它附近的白色牆面也呈現淡淡的紅色。全局光照模型更符合現實世界中,光線傳播的物理規律。能夠渲染出更加逼真的遊戲場景。 由於它的計算過程複雜,即使採用現有的主流圖形卡,遊戲畫面的繪製速度仍不夠快,難以滿足遊戲玩家的需求。

全局光照雖然可以獲得更好的視覺效果,但它的計算過程非常複雜,需要消耗大量的計算資源,很難用在電子遊戲和其他實時圖形- 程序裡面。為了克服全局光照的計算瓶頸,Unity 採用了一種稱為 Baked GI 烘焙全局光照技術,該技術採用預計算,也稱為烘焙方法,能夠提供不錯的全局光照效果。 烘焙過程只考慮場景中的靜態物體。

實現步驟如下:

  1. 在編輯階段,我們通過 Unity 編輯器,標記出遊戲場景中的靜態物體,也就是不會運動的物體。
  2. Unity 編輯器使用全局光照計算模型,計算這些靜態物體的光照效果,並將結果保存在光照紋理 Lightmap,這個過程稱為 Bake,烘焙。
  3. 在遊戲運行階段,Unity 引擎直接從 光照紋理 Lightmap 中獲取靜態遊戲對象的光照信息,用於遊戲場景的渲染。Unity 5.0 之後的版本還提供了一種名為預計算的實時全局光照,Precomputed Realtime GI 全局光照技術,這種技術和 Baked GI 一樣,需要烘焙階段只對靜態對象有效。 它在烘焙結果中保存的信息,和 Bake 截然不同。這些信息幫助 Unity 在運行時,快速計算全局光照效果。預計算實時全局光照的優點,在於它能夠允許動態改變遊戲場景中光源的數量、 位置、 朝向以及物體的材質和材質的屬性。

Precomputed Realtime GI 和 Baked GI 都能實現全局光照,有各自的優缺點。 Precomputed Realtime GI 的優勢在於允許實時改變光源的數量、 位置、 朝向以及物體的材質。但是,對設備的性能要求比較高,適合 PC 主機等計算性能比較強的遊戲硬體。Baked GI 雖然不允許實時改變光源屬性和材質,但軟陰影效果更好,運行時對設備的性能要求比較低,適合手機終端 Unity 提供的全局光照技術,雖然能夠產生逼真的視覺效果,也存在很多局限性。

  1. 由於全局光照計算的複雜性,Unity 編輯器需要花費較長的時間進行預計算
  2. 靜態物體在遊戲啟動後,位置一旦發生變化,預先計算好的光照效果就不再適用,所以全局光照只能對靜態物體才有效。 同理,非靜態物體反射的光線,無法影響其他物體,最後非靜態物體也無法直接受到烘焙光源和靜態物體反射光線的影響。

全局光照的使用方法

  • 選中需要應用的全局光照遊戲對象

  • 在 Inspector 視圖中,勾選 Static 下的 Lightmap Static

  • 點擊 Window 菜單下的 Lighting,打開 Lighting 設置窗口
  • 點擊 Lighting 窗口頂端中部的 Scene 按鈕,打開場景配置頁
  • 根據需要勾選 Precomputed Realtime GI 或者 Baked GI。也可以二者都勾選
  • 勾選窗口底部 Build 按鈕左側的 Auto 複選框

全局光照開啟後,需要設置光源的屬性。

光源的 Baking 屬性有三個可選項:

  • Baked
  • Realtime
  • Mixed

選擇 Baked,表示該光源用於 Baked GI 模式下烘焙光照紋理,無法對非靜態物體產生影響。選擇 Mixed 表示該光源除了用於 Baked GI 的烘焙,還會在運行時照亮非靜態物體。選擇 Realtime, 在沒有開啟任何全局光照的情況下,該光源使用局部光照,在開啟 Precomputed Realtime GI 情況下,該光源產生實時全局光照。

  • 執行完以上步驟後,Unity 會自動進行全局光照的預計算
  • 烘培的進度在 Unity 窗口的右下角顯示
  • 烘焙完成後,場景會自動應用全局光照的效果

在 Baked GI 模式下,每當我們增刪靜態物體或者修改靜態物體的屬性,修改 Baked 或者 Mixed 光源的屬性後, Unity 都會自動重新烘培,並在烘焙結束後自動應用全局光照效果。

在 Precomputed Realtime GI 模式下,每當我們增刪靜態物體或者修改靜態物體的一部分屬性後,Unity 都會重新進行烘焙,並在烘焙結束後自動應用全局光照效果。Precomputed Realtime GI 的一個優點是允許實時改變光源的數量、 位置、 朝向以及物體的材質。因此增加刪除或者修改光源和物體材質後,Unity 都不會進行重新烘焙。

面光源(Area Light) 只能在 Baked GI 模式下使用,烘焙完畢後可以看到效果。

Unity 全局光照的局限性

遊戲運行時,非靜態物體無法直接受到烘培光源和靜態反射光線的影響。比如遊戲運行時敵人的外表無法被照亮,顯得昏暗。

光照探頭

Light Probes 光照探頭技術用於解決全局光照模式下,非靜態物體與靜態場景之間光照不協調問題。利用光照探頭,可以在遊戲運行階段實時獲得非靜態物體的近似全局光照效果。

基本思想:

  • 編輯階段:在場景中放置光照探頭,並在探頭的位置對光照進行採樣,然後保存採樣數據
  • 運行階段:選擇非靜態物體附近的幾個光照探頭,使用這些探頭的採樣數據,插值獲得靜態物體應當受到的光照。

實現步驟:

  • 依此點擊菜單欄中的 GameObject->Light->Light Probe Group,向場景中添加一個光照探頭組。
  • 藉助一些工具幫助我們完成初步工作,把 LightProbePlacement.cs 腳本 拖入 Project 視圖中,在菜單欄中點擊 Window。 Window 菜單欄出現了 Generate Light Probes 選項。我們點擊該選項,打開光照探頭 Front 窗口。把剛才創建的光照探頭組對象拖放到該窗口的 Probe Game Object 組件欄中,然後點擊 Generate Probes 按鈕,開始生成光照探頭組。

  • 我們在場景中、 火炬附近的光影變化強烈的地方,以及光照探頭過於稀疏的地方,補充一些光照探頭。補充完畢後,我們再次打開 Lighting 窗口,點擊 Scene 標籤下的 Build 按鈕,重新烘焙全局光照。
  • 烘焙完畢後,發現場景中的殭屍和玩家對象,都能夠被火炬照亮。

光照探頭的調整原則

  • 在所有需要採樣光照或者陰影的地方添加光照探頭
  • 探頭應該組成一個空間立體網格,覆蓋非靜態對象可能到達的所有位置
  • 光照變化平緩的地方,光照探頭應較為稀疏
  • 光照變化劇烈的地方,光照探頭應較為密集

附加閱讀:

  1. 全局光照 (docs.unity3d.com/Manual)
  2. 光照探頭 (docs.unity3d.com/Manual)

推薦閱讀:

在Unity中復刻《超級馬里奧》
用好Lua+Unity,讓性能飛起來——Lua與C#交互篇
Unity什麼時候應該手動進行視域Culling?
Billboards 技術在Unity 中的幾種使用方法
300行代碼實現Minecraft(我的世界)大地圖生成

TAG:计算机图形学 | Unity游戏引擎 | 物理学 |