[转载]Unity5灯光GI烘焙优化

发布于 2018-04-27  21 次阅读


场景下载地址:点这里

翻譯:Kelvin Lo

介紹

在Unity裡,可以用兩種不同的技術來計算全域光照GI或光源反射,就是烘焙全域光照(Baked GI)和預計算即時全域光照(Precomputed Realtime GI),這份教學文章主要是說明預計算即時GI-本文將以PRGI作為簡稱。

當啟用PRGI時,一個光照預計算就是用來計算靜態幾何物件周圍光的反射,並存成資料給Runtime執行使用的一個過程。這個過程減少了原本必須在Runtime執行時的光照計算數量,讓專案得以在保持FPS的穩定之下還能計算光的反射。

當啟用烘焙GI(Baked GI)時,預計算的過程會計算並產生傳統的光照貼圖(Lightmap),這些貼圖會以資源(Assets)的形式存在專案中,而且無法再Runtime執行時更改。PRGI並非用一樣的方法產生光照貼圖,相反的,PRGI算好的結果會被存成一個光照資料檔(Lighting Data Asset),這個資料檔存的資料能讓專案在Runtime執行時能即時產生一組低解析度的光照圖。

除非場景已經為了PRGI計算優化過,否則完成這些計算所需要的時間可能會很長。在本文我們將學習如何針對Enlighten系統(Unity用來計算全域光照的系統)來優化一個場景,讓預計算只需要幾分鐘而非幾小時。

過程將會涵蓋:

  • 如何定義一個適合場景的光照解析度
  • 何謂光照圖(Charts),它如何影響到計算的時間
  • 如何開始一個預計算
  • 使用光照探針來降低光照方案的複雜度
  • 改進Unity PRGI的自動拆解UV結果
  • 何謂叢集,如何用它來產生GI照明
  • 以物件為基礎使用光照貼圖參數微調光照
  • 一旦我們學習並了解這些技術,我們就可以利用PRGI的優點:快速迭代的時間,針對預計算光照或遊戲裡的即時光照反射就能更快進行不同實驗測試的能力。

將預計算的時間從幾小時降低到幾分鐘

這個教學所用到的場景裡,用沒有優化過的預設設定在我們的測試機上計算光照大約花了7.5個小時。對於這種複雜場景顯然這是無法接受的時間。
[转载]Unity5灯光GI烘焙优化插图
無優化場景(上圖):預計算7.5小時,有優化場景(下圖):預計算2.25分鐘。

使用本教學所介紹的技術進行大約30分鐘的場景準備後,這個場景的預計算花了2.25分鐘得到一個產品等級的結果。考慮到我們可以在遊戲過程中快速迭代場景照明而不需要重新計算GI和改變GI照明,這個技術的好處是顯而易見的。

下載本教學的素材包

本教學採用Asset Store上的官方光照優化素材包
本教學所用的是Scenes/Article目錄底下的範例場景: LightingTutorialOptimal, LightingTutorialNonOptimal 以及 LightingTutorialStart.

  • LightingTutorialOptimal已經根據這個教學設定好,用來展示PRGI如何設定能用最短的時間呈現出產品等級的結果。
  • LightingTutorialNonOptimal呈現了我們在專案中常看到的問題,要嘛造成無法烘焙,要嘛花費無法接受的時間烘焙,這是一個很好的錯誤示範。
  • LightingTutorialStart將會是我們在教學過程中用到的場景,我們會按照步驟一步一步將它變成一個產品等級的結果

即時解析度

當使用PRGI來計算場景照明時,首先要做出的決定之一是確定場景的即時解析度(Realtime Resolution),它決定每個世界單位(World unit)所使用即時光照的貼圖像素(Texture pixels)數量。

Realtime Resolution設定可以從Lighting介面找到並調整,方法如下:

  • 開啟Lighting介面(Window > Lighting)並選擇Scene頁籤
  • 確保Precomputed Realtime GI旁的勾是打勾的
  • 在它下面找到Realtime Resolution屬性

[转载]Unity5灯光GI烘焙优化插图1
Unity的Lighting介面主要顯示整個場景會用到的光照設定

選擇適當的解析度

當設定場景時,很重要的是要了解你的專案需要的單位比例,可能在你的專案裡一個單位等於現實世界的1米、一英尺或一公分,Unity沒有預設真實世界的單元,所以得由開發者自行決定。

在這個範例裡我們採用1 unit(單位) = 1 meter(米)。因為這和Unity的物理概念不謀而合,舉例來說Unity的重力預設就是以每秒多少單位來計算,因此設定1單位 = 1米就是一個很好的真實世界場景設定。

Realtime Resolution的值可以由你的遊戲規模來制定,例如,是否你的場景是一個小小的,卻有豐富光照變化的室內環境? 在這種情況下,高一點的值比如2-3,可以捕捉更詳細或"高頻"的光照。

如果你的場景是一個世界規模較大的大型戶外環境。可能有著幾千或幾百個物件表面幾乎不會去修改光照反射顏色。在這樣的情況下,把適合計算複雜室內場景的設定用在有大量相同特徵的室外環境是很浪費的。我們會浪費寶貴的CPU時間和記憶體儲存/更新那些對整體外觀貢獻不大的光照貼圖。為了教學目的,我們會提高PRGI期間必須考慮貼圖像素的量,這會對預計算的時間造成很大的影響。

在場景裡有大物件的室外環境情況下,合適的設定可以設在0.5-1之間,針對地形可以設定0.1-0.5之間。

預計算即時GI解析度 VS 傳統光照貼圖

Unity PRGI所需要的Realtime Resolution值比傳統光照貼圖密度要小好幾個等級,這是因為我們只從這些光照圖裡擷取間接光源資料,這些資料通常解析度都很低。所以使用PRGI時,清晰的陰影通常都是即時運算而非從高解析度的光照圖來提供。

在這裡使用傳統光照慣用的值,例如:30 texels,可能會導致預計算失敗或無法計算。室內場景比較適合的值是2-3,室外場景則是0.5-1。這是假設我們用的單位是1單位 = 1米的前提下,如果單位大小不同這些值就需要調整。

場景與Realtime Resolution值對照表

場景Realtime Resolution
室內2-3像素/單位
戶外0.5-1 像素/單位
地形0.1-0.5 像素/單位

*假設人類規模的世界,1單位代表1米適當的設定

當設定場景即時解析度時,Unity會指定給場景內的靜態物件。帶有Mesh Renderer且標有靜態光照標籤(Lightmap Static)的物件,會引用這個值一直到它被外力修改。

除了幫場景加上解析度設定外,我們還能針對每個物件調整光照貼圖的解析度,在需要高解析度來提供更高真實感的情況下,我們可以選擇性的提高這個值。通常是將場上最多的物件解析度設為預設值,然後手動調高需要更多照明細節物件的值。本章後面會說明如何修改每個物件解析度的方法。

設定場景的即時解析度

如果你想跟著做,可以打開教學素材包裡的LightingTutorialStart場景。
在範例場景裡,我們有一個戶外環境,中等大小的地形與相當一致的色調。所以我們設定Realtime Resolution為0.5像素/單位就足以處理從場景其他物件來的光照反射。然而,場景裡也有些貼圖細膩的木屋。由於場景裡有比地形物件還多的房子,我們應該把預設的解析度設定適合房子的數值。然後我們可以單獨修改地形物件的解析度,這樣可以降低場景準備的工作量。考慮到這點,我們用1作為我們的預設解析度。

  • 開啟Lighting介面(Window > Lighting) 然後選擇Scene頁籤
  • 設定Realtime Resolution值為1

有鑑於我們的世界單位設定為1單位 = 1米,這表示由PRGI所產生的光照圖將會是1x1米的大小,或許你看起來很低,那是因為我們只抓取間接光照。還會從場景裡的直接光源計算清晰的陰影和反光。

了解光照圖

在Unity PRGI裡,一個光照圖(Chart)是表示一個光照貼圖的區域,用來映射場景物件的光照貼圖UV。你可以想像是能影響物件的一張小磁磚圖,一張光照圖由兩部分組成:輻照度(照明)和方向性(主要光線方向編碼)。

當產生PRGI資料時,圖表裡的每個單位都會被計算光照。換句話說,場景裡面有大量的光照圖可能會是PRGI耗時的原因之一,因此了解光照圖的運作原理以及如何管理它們來優化光照計算的時間是很重要的。
[转载]Unity5灯光GI烘焙优化插图2
如圖所示一個最小4x4單位的UV光照圖,為了防止貼圖過濾造成的滲色,UV貼圖始終被光照圖包住並隔出一半單位(本例是0.5)的大小。

在預設的情況下,每張光照圖最少要有4x4單位大小,所以說不管世界中的物體大小或對應的UV大小,一張圖表至少需要16個貼圖像素(texels)。因此如果有一個1x1米的物件並帶有一個圖表,間接解析度是1,那這個物件就會需要16 texels來表現。最後Unity會將這些圖表縫合再一起,作為模型邊緣的光線取樣參考。Unity需要每張圖表的邊緣至少有4個像素單位,方便在縫合不同光照圖時有對照的依據。

要注意的是使用即時GI時是不需要自己去填這些UV的邊,因為Unity在處理網格匯入的流程時會自動將光照UV圖往內擠出一個邊框的空間。這樣就能讓相鄰的圖表不用做滲色處裡還能保持雙線性內插(bilinearly interpolated),能節省寶貴的光照貼圖空間。

試想我們之前說的1x1物件如果帶有50張光照圖,Unity會為它產生800個貼圖像素,就算它聽起來沒很大,但這說明了當圖表的量一大就會快速拉高貼圖像素的量。越多的貼圖像素代表更重的光照運算要處裡,更多的光照資料要計算、壓縮和儲存,這些要素都會讓場景更複雜,並導致漫長的計算時間和低落的效能。

不當的光照圖規劃是導致計算耗時太久或無法完成的主因,也因為如此,我們許多減少計算時間的方向大多都是思考如何降低場景內光照圖的數量。

開始預計算

要計算全域光照就要啟動PRGI流程,在開始之前場景裡面最少必須要有一個物件被標為靜態物件(Lightmap Static)。

透過層級視窗(Hierarchy)的功能,你可以輕鬆管理並選擇哪些物件要用來計算光照。有非常多的方法來管理這些物件,但這不是今天教學討論的目的,重點就是好的物件管理流程可以大大提升物件的利用率。

在我們的範例裡,我們會把物件都放在一個名為"Environment"的父物件底下來管理,這個群組會放所有看的到並帶有MeshRenderer元件,用來組成場景環境的靜態物件。在它底下還會有一些放有各種場景物件的子群組。
[转载]Unity5灯光GI烘焙优化插图3
對場景內的物件分類有助於頻繁重複選擇物件的操作

開始最好的做法是先從Lighting設定裡先設定初步大方向,然後邊做邊調整細節設定。

  • 選擇場景裡的"Environment"物件
  • 從檢視(Inspector)視窗,把右上方的Static打勾
  • 如果系統跳出一個詢問視窗問你是否要把底下的子物件也一起標記為靜態物件,請選擇"Yes, change children"。這樣就能確保所有在Environment裡的物件都變為靜態物件並列入光照計算。

現在場景內有了一些靜態物件之後,我們就可以開始計算GI了。

  • 打開Lighting介面(Window > Lighting) 然後選擇Scene頁籤
  • 確認最底下的Auto有打勾(最底下的Build按鈕旁,如果打勾Build按鈕會灰掉)
  • 然後系統就會開始計算光照。畫面的右下角會出現一個藍色的進度條,顯示目前的工作(幾分之幾)以及有多少工作要計算。
  • 在Auto沒打勾的情況下,你也可以手動按Build,系統會先問你是否要存檔後開始計算光照。這次的教學建議把Auto打勾即可。

[转载]Unity5灯光GI烘焙优化插图4
進度條顯示目前進度並提示還有多少工作等著計算

光照探測

我們已經理解場景裡的圖表數量對預計算時間的影響,這樣我們就能從預計算流程裡想辦法降低一些物件計算來讓光照效能大躍進,同時也會減少圖表產生的數量.取而代之的,我們可以對這些物件做光照探測(Probe Lighting)處理,它是一種讓物件接收場景間接照明的好方法,雖然被光照探針指定的物件無法計算場景的光照反射,但通常影響不大。這種方法非常適合用在場景裡的小物件,因為小物件對光照反射計算幾乎沒什麼影響。

何謂光照探測

光照探測技術是一個能在遊戲裡讓即時光照更逼真的快速演算法,通常會用在處理遊戲世界的人物角色或是動態物件的光照,它的優點在於Runtime處理效能佳而且還能預先計算好。

光照探測的原理是透過放在3D空間裡的探針來接收照明資訊,然後用像是球諧函數(spherical harmonics)的數學演算法將結果編碼在一個球體上。這些係數佔用空間很小在遊戲過程裡能快速"解包",好讓Shader可以存取並計算表面光照,在Unity裡這個功能叫做Light Probes。

使用光照探測是有些限制的,其中一個限制是在不提高探針數量的前提下很難在球型範圍上表現出高頻或斑駁的光照,但精度和消耗成本成正比,代表在效能的前提下,我們必須限制較低階的球諧函數。

實際上一個3D座標只能用一個球體來紀錄照明資料,所以光照探測不適合用在有大量光照投射在大物件的狀況。另外一個限制是當用球諧函數在一個球體上編碼時,通常不擅於處理用有廣大平面的物件或帶有很深的凹洞的物件.如果你正計畫要把光照探測技術用在大型物件上,Unity有提供另一個光照探測代理體(Light Probe Proxy Volumes,LPPV)的技術可以參考手冊說明。

儘管有這些限制,光照探測還是很適合和符合條件的小物件一起搭配使用,產生成本低廉效果卓越的結果。在本教學後面我們將會深入探討如何設定和放置光照探針(Light Probes),現在我們只需要理解適當的使用光照探測這功能可以降低光照貼圖的數量。

幫物件設定光照探針

儘管一次將環境裡所有的物件設定為靜態物件來做光照計算是很OK的,但是整個環境裡有很多物件很適合用光照探測技術來處理,把這些物件的靜態標籤清除之後,他們就不再受到PRGI計算影響,同時光照貼圖的數量也會降低。減少場景裡光照圖的數量是加快預計算時間的關鍵。
[转载]Unity5灯光GI烘焙优化插图5
使用光照探測的最佳物件就是像這種凸起的小碎石

我們從Unity編輯器的Hierarchy視窗來看看環境(Environment物件)底下的子物件,你會發現Props底下的物件幾乎都是點綴場景用的小物件,像是石頭,水桶或木板。這些物件非常多,而且很多小物件可能不太好拆UV。取得沒有失真的光照貼圖UV可能會產生很多UV Shell,一旦UV Shell一多就會需要額外的光照圖,更多的光照圖代表更多的貼圖像素產生,依此類推。

假設這些物件很小,不太可能對場景的間接照明產生什麼影響,因為小所以表面能顯示的光照細節也有限,所以這樣的物件非常適合用光照探測技術來計算,不但可以加速預計算時間,同時要存到記憶體的光照圖和Shader解碼的數量也變少了,在Runtime時的效能也會因此提升。

  • 從Hierarchy視窗選擇Props物件
  • 從Inspector視窗把最右上角的Static取消打勾
  • 這時會跳出一個視窗,選擇"Yes, change children"

如果這時我們放著算到完就能看到場景最終的光照運算結果,但你會發現被探測光影響的非靜態物件(non-Static objects)和周圍的物件有點格格不入,和場景的光照也不匹配。這是因為我們還沒幫光照探針(Light Probes)做設定,導致這些物件被納入環境探針(Ambient Probe)的計算。環境探針本質上是一個在場景裡無法看到的隱形探測器,只對Lighting視窗裡的Ambient Source所指定的來源取樣。
[转载]Unity5灯光GI烘焙优化插图6
在沒有光照探針影響下,非靜態物件可能看起來不像在他們應該在的地方

為了將非靜態物件擺起來的結果更令人信服,我們需要花點時間來將光照探針放置在場景的周圍,方便取樣世界裡的間接照明。

放置光照探針

非靜態物件會透過附近的光照探針來接收光照資料,光照探針會基於探針之間的空間劃分為四角面,然後檢查物件屬於哪個四角面來決定物件"讀取"哪個探針。為了正確的產生這些四角面,探針間的位置關係在3D空間裡就必須要放的有體積感。
[转载]Unity5灯光GI烘焙优化插图7
畫面中那些白色的球體就是光照探針在場景裡的樣子

光照探測技術執行所耗的效能非常低,預計算也非常快,然而,為了要最佳化效能有些地方要注意一下,儘管設定簡單,但密度太高的探針可能會浪費資源,太接近的探針在特定的光照條件下取樣結果沒什麼差異。為了效率最好的做法是在光照變化明顯的區域放置密度較高的探針,例如由亮轉暗的區域,或是強光反射的區域。

  • 要設定光照探針,可以從物件選單建立一個光探針群組(GameObject > Light > Light Probe Group)
  • 開始放置光照探針,從Hierarchy視窗選擇剛建好的光探針群組物件
  • 從Inspector視窗裡找到Light Probe Group元件,選擇Edit Light Probes開始編輯
  • 你可以從場景直接點選那些探針,留下角落一個探針,其他可以全刪了
  • 將剩下的一個探針移到地形上面一點點,然後按Ctrl + D( Mac是按Cmd + D)來複製它
  • 用移動工具(按W)將複製的二號探針沿著Y軸往上約2米(2 meters)
  • 再複製一次探頭,並將新探頭的Y軸往上移更高,約5米

[转载]Unity5灯光GI烘焙优化插图8
Light Probe Group元件裡的Edit Light Probes按鈕位置

這樣的垂直探針分佈為的是讓我們可以同時取樣到地表,頭部高度和天空(考慮到物體可能跳躍的高度)的間接光照(indirect light)。當我們將這組光照探針開始大量複製到場景其他地方來產生光照探測區域時,要確保可玩區域都會被探針所產生的四角面覆蓋到,可以看到探針之間會以洋紅色的線串聯起這些區域。
[转载]Unity5灯光GI烘焙优化插图9
如圖所示光照探針的位置和他們之間所產生的四角面

  • 全選剛剛建立好的三個探針(按住Shift並點選每個探針或是拉一個框選起來)
  • 複製整個探針組並移到場景其他需要採樣的地方

說到需要採樣的地方不外乎是有陰影的區域或是地形材質色調會變化的地方,請記住,我們的目的是取樣場景裡的間接或反射光照。為了讓每個光照探頭效能都花在刀口上,儘量確保他們對一些變化明顯的地方進行取樣,如果探針放在一致性很高的光照區域,那探針反映給動態物體的結果不會太明顯。如同遊戲優化各方面技巧一樣,儘量確保每個探針都是有其存在的必要。

  • 繼續重複上述操作,在照明區域大密度的放置光照探針直到產生了一個像是籠子般的區域涵蓋所有的可玩區域。
  • 佈置這些探針時,請記得每一次都要檢查最底部的探針要和地面保持一定的距離。

我們的範例檔LightingTutorialOptimal裡面附了兩組光照探針,VillageLightProbeGroup比較密集用在村莊區域,ExtentsLightProbeGroup比較稀疏用在村莊外無法到達的區域。第二個光照探針組涵蓋了整個遊戲世界以防止任何非靜態物件離開可玩區域,這一組不需要像村莊那組探針那麼密集,垂直軸只要兩個探針就夠了。

將光照探針拆成兩組方便定義探針用途,每個探針組都可以獨立開啟或關閉方便因應場景各種需求,這些光照探針在Runtime執行的時候會自動組合並執行重疊檢查(de-duplication pass)刪除所有重疊的探針。

要看到光照探針的照明結果,必須等到預計算完成,如果Lighting視窗(Window > Lighting)底下的Auto是打勾的話計算就會自動進行,如果沒打勾就要按一下旁邊的Build按鈕來手動計算。

一旦計算完成後,你會發現場景裡面的非靜態物件會開始接收光照探針的資料,看起來和場景光源會更匹配。要查看點燈狀態下的光照探針,可以從Hierarchy視窗選擇光照探針組。

現在場景裡有了光照探針組,我們就能幫場景裡的小物件取得間接光照資料,而不需要從PRGI的流程中為這些物件產生額外的光照圖。

拆解與減少光照圖

上一章我們已經排除掉一些不需要計算即時光照的物件,現在可以開始幫剩下的光照圖繼續做瘦身工作。

產生光照圖(Charts)的目的主要是用來包住靜態網格著色器(Static Mesh Renderer)的UV貼圖座標。一個物件所需要的光照圖數量主要是看物件有多少片UV shell需要拆解。所謂拆UV的學問就是保持幾何面上貼圖像素扭曲度和所需的Shell數量之間的平衡。

一般來說Unity的拆解演算法能拆出不錯的結果,但有時候我們會需要手動調些設定,因此是有必要了解一下自動拆解功能背後的運作原理。

看看下列範例圖:
[转载]Unity5灯光GI烘焙优化插图10
這樣的UV拆解不會變形,但需要多張UV shells

[转载]Unity5灯光GI烘焙优化插图11
用單一UV shell所產生的結果,但貼圖變形很嚴重

[转载]Unity5灯光GI烘焙优化插图12
比較理想的結果,單一UV shell且貼圖沒有變形

從上面我們可以看到三個拆UV不同的例子

從第一張圖裡我們可以看到做為貼圖的棋盤格圖案像磁磚一樣保持比例的貼在方塊表面上並沒有變形。試想如果這個棋盤圖案是一個光照貼圖(一個打在物件上的光照圖像),我們會得到一個視覺上看起來沒有問題的結果,只是會需要耗費六個UV shells。那就表示待會用Unity PRGI計算的時候也會產生六張光照圖,不管條件如何,每個光照圖最少都需要4x4個貼圖像素來表示,還沒考慮解析度之前最少就會耗掉96個像素。

在第二張圖裡我們會遇到不同的狀況,物件的UV貼圖座標只用一個UV shell就涵蓋所有範圍,雖然這樣所產生的光照圖最少,但視覺效果卻不是我們要的。我們會看到物件表面上的貼圖歪掉了,貼圖在UV空間裡也相互重疊,代表如果這是一張光照貼圖,物件一面的光照可能會錯投到相反面上。很明顯的這種拆法是有問題的。

第三張圖的結果比較理想,棋盤沒有扭曲,磁磚比例也保持正方形。而且還成功用一張UV shell覆蓋物體的所有面。屆時透過連接或縫合對應在模型上的邊緣來把位置合上。
如果用技術的邏輯來看,整個過程做了哪些事情呢? 首先,我們會將UV圖用正交投影(Orthogonal Projection)在物件上來產生獨立的Shell,然後我們就會分析哪些Shell和物件的邊緣有相連關係,一旦我們找到了這些邊緣,我們就會把UV shell的內容移進去並和相鄰的Shell縫合起來。

可視化的光照圖

在開始優化我們的拆解流程和光照圖之前,我們需要有個方法從編輯器來檢視它們。光照圖是在網格導入流程的一個拆解階段(Unwrapping stage)被產生出來的。對於PRGI來說,這些光照圖會在預計算裡的幾何階段(Geometry stage)被打包到不同的圖集(Atlas)裡,這是為了確保它們不會相互重疊。一旦預計算的幾何階段完成之後就會產生可視化數據,我們就能預覽光照圖。

如果你用版本控制(Version control)管理,請注意,這個預覽資料只會儲存在本機,所以在開始檢查之前要執行預計算一次。
[转载]Unity5灯光GI烘焙优化插图13
UV Charts模式會把場景裡不同光照圖用不同顏色表示,光照貼圖解析度會用棋盤格表示疊在上面

要快速檢視光照圖可以在場景視窗切換UV Charts繪製模式

  • 從場景視角(Scene View)左上方的Draw mode下拉選單找到UV Charts。

在這個模式下,光照圖會用不同的顏色和一個表示解析度的棋盤圖疊在一起,如果自動烘焙模式是啟用的(Window > Lighting > Auto),也會自動計算拆解變數的變動並更新在場景視窗上。
[转载]Unity5灯光GI烘焙优化插图14
Charting模式的預覽視窗會用不同的顏色的格子表示光照圖,並用淺藍色的線表示UV貼圖。

當場景複雜的時候從場景視窗有可能會漏看光照圖。如果從Lighting視窗用預覽模式的話,我們就可以針對查看單一物件查看它所有使用的光照圖。這樣可以幫我們更精準的評估這些物件拆解結果,有助於降低光照圖的數量。

  • 打開Lighting介面(Window > Lighting),選擇Object頁籤。
  • 從Hierarchy視窗選擇你想檢視的物件。
  • Lighting視窗裡的預覽窗格,從最上面的下拉式選單選擇Charting模式。

物件耗用的光照圖數量會以不同顏色的方塊疊在對應的淺藍色UV座標上。

拆解參數說明

有幾個設定有助於拆UV的優化,所有的設定都是針對單一物件,我們可以透過下列流程來設定:

  • 開啟Lighting介面(Window > Lighting) 並選擇Object頁籤
  • 從Hierarchy視窗裡選擇你要設定的物件

Auto UV Max Distance(自動最大UV距離)

Unity的拆解演算法會嘗試把不同Shell做調整將UV邊緣拼接在一起來簡化UV貼圖。當Shell放入後還能保持在Auto UV Max Distance規定的範圍內時才會被考慮進來。這個範圍是用Unity的世界空間座標來定義的,在我們的範例裡是1米。
[转载]Unity5灯光GI烘焙优化插图15
Auto UV Max Distance設定可以從Lighting視窗裡的Object頁籤找到

在許多情況下,預設的0.5就能給出不錯的結果,但對於具有大面積的特大物件可能要提高這個值來防止本來應該被縫合的UV圖被演算法排除在外。

增加這個值通常會讓物件所需的光照圖數量減少,而降低這個值通常有助於解決貼圖像素被拉扯的問題,當然就會需要產生更多的光照圖來覆蓋。改變這個值後你可以透過檢視場景UV Charts繪製模式,從覆蓋的棋盤圖來評估並實驗出一個最好的平衡點。

Auto UV Max Angle(自動最大UV角度)

拆UV的計算當然也會考慮到相鄰Shell的角度,Auto UV Max Angle定義相鄰面共享邊緣允許的最大角度,並用內角來計算如果背面的角度大於這個值,就會排除縫合這個UV Shell。
[转载]Unity5灯光GI烘焙优化插图16
Auto UV Max Angle設定可以從Lighting視窗裡的Object頁籤找到

提高這個值會讓Unity的演算法更容易組合UV圖,這也表示能透過這個功能來降低單一物件的光照圖數量,但是如果設的太寬鬆有時候會出現貼圖被拉扯的狀況。反之降低這個值會造成演算法不好把相鄰的UV排一起,雖然拉扯的情況會降低但是會產生更多光照圖。相同,檢視UV Charts繪製模式裡的棋盤圖並試出一個最適合的值。

Preserve UVs(保留UV)

在某些情況下,自動拆UV如果無法獲得理想結果,可能會產生過多的光照圖或是貼圖失真(GI Charts繪製模式可以做拉扯檢查)。在這種情況下可能需要在模型的UV01通道手動建立UV。這必須要在其他工具完成。

如果這種情況發生,我們可以在Preserve UVs選項讓Unity演算法強制採用模型UV01通道指定的UV Shell。
[转载]Unity5灯光GI烘焙优化插图17
當需要手動保持UV圖時,Preserve UVs選項很有用

要注意的是這些Shell會被重新打包來節省光照貼圖空間,它們會被單獨解開保留,而不是只有把在光照貼圖內的座標記錄起來而已。

使用這個功能時必須小心,當指定的UV貼圖包含著大量的UV shells時,這個功能可能會讓預計算的時間拉長,因為Unity的拆解演算法被跳過,手動保留的UV Shells到時候會全餵給預計算流程。記住,最好的結果是儘可能的降低UV shells和光照圖並保持可以接受的貼圖拉扯範圍。

Ignore Normals(忽略法線)

在某些情況下,網格匯入器可能會拆開幾何圖形,這也會影響到光照圖的數量。例如,如果有個網格有非常多的三角面,Unity可以為了效能把它分割成幾個獨立的子網格。通常這麼做是為了符合特定硬體需求,例如為了減少每個Draw Call所需要呼叫的三角面數量。分割通常會發生在相鄰的網格面之間法向角度有大變化的區域,比如銳角邊(hard edges)。這樣的拆分網格方式會在模型導入流程時執行,在這個過程中,UV Shell也可能會被拆分開來放到不同的光照圖,造成額外的光照圖消耗。
[转载]Unity5灯光GI烘焙优化插图18
Ignore Normals選項可以防止模型在匯入時光照圖被拆開

有時候放著上述的問題不管不太值得,得到的結果讓光照圖數量增加拉長了預計算的時間,還有可能在照明的接縫造成不必要的視覺假象。在這樣的情況下,啟用Ignore Normals選項有助於防止光照圖在預計算的時候被分割開來。

請注意,這個選項只有對預計算即時光照(PRGI)有影響,物件被拆分的網格仍然會被保留以用在其他用途。

大場景中更快的迭代

複雜的場景可能包含著上百或上千的靜態物件,幫這些物件計算光照圖集可能會導致預計算變很慢,對我們在場景的迭代速度產生負面影響。

當你在測試研究上述設定時,有時候把物件換到空場景是很有幫助的,這樣可以用最小的預計算時間來快速迭代。測好設定之後可以把設定貼回原本場景裡其他的同類型物件,這樣可以節省時間。

打開範例裡的LightingTutorialStart場景

  • 從Hierarchy介面裡選擇HouseBig02物件,他們在Environment > Structures > Houses。
  • 按Ctrl + C複製這個物件(Mac是Cmd +C)
  • 按Ctrl+N建立一個新的場景(Mac是Cmd+N)
  • 可能會有提示問你是否要存檔,選Yes可存檔,選No可不存檔。
  • 在新的空場景裡按Ctrl+V把房子貼上(Mac是Cmd+V)
  • 打開Lighting介面(Window > Lighting)選擇Scene頁籤
  • 確保最下面的Auto有打勾
  • 選擇Object頁籤
  • 最上面左邊的下拉式選單選擇Charting
  • 拉大預覽視窗的區域來查看物件拆解的狀況

調整拆解設定,優化預計算時間

當調整拆解設定時,最好的結果是找到能產生最少光照圖與最低失真度的參數組合。請記住,當啟用UV Charts繪製模式時,失真的程度能從場景裡的棋盤圖拉扯狀況來評估。
[转载]Unity5灯光GI烘焙优化插图19
棋盤圖案用來可視化光照貼圖的分佈,這張圖呈現出棋盤圖和模型的一致性,代表失真度低
[转载]Unity5灯光GI烘焙优化插图20
棋盤圖在模型表面被拉扯表示和光照圖的分配不一致

接下來我們會用教學範例來實現我們所學關於UV拆解與優化預計算時間的方法。

  • 開啟範例裡的LightingTutorialStart場景
  • 從Hierarchy介面裡選擇HouseBig02物件(Environment > Structures > Houses)
  • 打開Lighting介面(Window > Lighting)並選擇Object頁籤
  • 從上方左邊的下拉式功能表選擇Charting
  • 展開預覽視窗,注意這裡顯示了多少UV shells與對應顏色的光照圖數量。

[转载]Unity5灯光GI烘焙优化插图21
上圖表示用Charting預覽檢視預設設定下的HouseBig02物件,這個結果還有很大的優化的空間。

HouseBig02是場景裡一個複雜的物件,用了許多光照圖來詮釋,但還有空間調整設定來減少光照圖的數量。
[转载]Unity5灯光GI烘焙优化插图22
拆解設定畫面

沒有一個固定尺寸能符合全部狀況,Unity的拆解演算法會基於預設值適當的決定,但是透過一些經驗的累積,可以微調出更好的結果。

  • 從Hierarchy視窗裡選擇HouseBig02物件
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 調整Auto UV Max Distance為0.1

接下來預計算會開始啟動,經過短暫的計算時間後,我們可以從預覽視窗看到光照圖數量明顯增加許多,檢查場景視窗可以看到貼圖只有一點拉扯,這是好現象。但我們無法接受多了這麼多光照圖。因為光照圖一多代表預計算時間會變長,效能也會降低。

  • 從Hierarchy視窗再次點選HouseBig02
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 調整Auto UV Max Distance為10

現在問題應該會反過來,光照圖的數量會降低,但你可以從UV Charts繪製模式裡看到,光照圖拉扯的問題會變得很嚴重。
[转载]Unity5灯光GI烘焙优化插图23
值太高可能會導致UV會被拉扯到

Unity會嘗試把UV Shells合併來最小化光照圖的數量,當兩個Shell要合併時會把這個值一併列入考慮,如果兩個Shell的距離大於這個值,就不會被合併。

所以當我們把這個值調低時,被合併的UV Shell就變少。這代表最後會產生很多單獨的光照圖。而當我們調高這個值時,距離很遠的UV Shell都會被考慮合併,就會產生比較少的光照圖,但相對的也會讓光照圖容易產生扭曲。

對於大物件有時候可能需要調高這個值來確保整個網格面積都涵蓋到,相反的如果是小物件也可以調低這個值來產生更好的結果。

以我們的範例HouseBig02來說,設定0.8的Auto UV Max Distance是一個好的平衡點。

  • 從Hierarchy視窗再次點選HouseBig02
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 調整Auto UV Max Distance為0.8

[转载]Unity5灯光GI烘焙优化插图24
設定為0.8得到一個不錯的結果。但我們還能繼續改善

現在我們來看看Auto UV Max Angle參數,和距離一樣,這個值影響著Unity拆解演算法的結果,演算法除了會評估距離之外也會評估相鄰網格之間的角度,角度低於這個值才會被合併。

較小的角度代表更低的通過率,更少的UV Shell被合併,以及更多的光照圖產生。相反,較大的角度代表演算法能容忍的角度更大,更多的UV Shell能被合併。和距離的情況一樣,結果會減少光照圖的數量,但是會有變形的問題。

  • 從Hierarchy視窗再次點選HouseBig02
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 設定Auto UV Max Angle為0

從預覽視窗能看到所產生的光照圖高的不像話,那是因為我們只允許0或更小的角度才考慮合併,這代表沒有UV Shell會被合併,每個都會獨立產生光照圖。
[转载]Unity5灯光GI烘焙优化插图25
太小的角度設定會造成產生過多的光照圖

接下來我們來試試看把角度調大:

  • 從Hierarchy視窗再次點選HouseBig02
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 慢慢調高Auto UV Max Angle,觀察預覽視窗裡面的結果

可想而知,光照圖的數量會隨著角度增加而減少,這是因為更多的UV Shell允許被合併,UV Shell數量降低光照圖就變少。
[转载]Unity5灯光GI烘焙优化插图26
加大角度有助於減少光照圖,尤其是在具有圓形表面的物體上

以這個案例來說,將這個值設為93對於HouseBig02可以得到最好的結果。

  • 從Hierarchy視窗再次點選HouseBig02
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 設定Auto UV Max Angle為93

注意在計算之後減少了多少光照圖
[转载]Unity5灯光GI烘焙优化插图27
從Charting預覽看到優化之後的HouseBig02

到這裡你可以把這些測試出來的設定帶回原本的場景,步驟有點複雜請注意:

  • 從Hierarchy視窗再次點選HouseBig02
  • 從Inspector視窗找到Mesh Renderer元件,點選上面的齒輪按鈕後選擇Copy Component。
  • 重新開啟LightingTutorialStart場景
  • 從Hierarchy視窗找到原本的HouseBig02的目錄
  • 按住Ctrl(Mac按住Cmd)然後把所有的HouseBig02一一點選起來。
  • 開啟Lighting介面(Window > Lighting) 選擇Object頁籤
  • 點一下齒輪,選擇Paste Component Values,剛剛調好的設定就會反映到全部選起來的HouseBig02物件

[转载]Unity5灯光GI烘焙优化插图28
用Copy Component是一個簡單的管道來複製設定到另外一個場景

當必須針對場景好幾百個物件調整設定時,這樣的操作能更節省來把時間花在其他優化上

拆解設定:實例(pre-instance)還是預製(pre-Prefab)好?

拆解設定可以存在預制物件(Prefab)裡,只要把這些帶有Static Mesh Renderer元件的物件存成Prefab即可,或是直接把設定指給場景裡的物件也行。

如果拆解設定是貼在一個經過Prefab實例化(instance)的物件,那麼會蓋掉原本在Prefab裡的設定,在某些情況下能幫場景做些不同的變化。

做一個預設Prefab用來作為拆UV和光照設定的基礎物件是很不錯的,如果Prefab需要常被實例化,這麼做就能節省一些設定的時間。

另一方面來說,這種做法蠻適合基於場景不同的物件配置來指定拆解設定,例如,在離玩家近的區域內看到的預制物件可以設定更好品質,反而如果物件離很遠,那用同樣的設定就沒甚麼意義,這裡應該降低光照貼圖品質,並積極的降低光照圖的數量。

可以設定一個符合大部分的狀況的設定,然後在需要的情況下去覆蓋這些設定,在本次教學裡,我們會針對每個實例物件來設定。

幫場景指定拆解設定

現在是時候將所學應用到這個教學場景。有系統的執行應該不會花太久的時間來設定。

  • 開啟LightingTutorialStart場景
  • 從Hierarchy視窗Environment > Structures 找到最上面的物件
  • 把這個物件複製到一個空場景

到這裡我們應該用我們所學,嘗試各種不同的值,善用UV Charts繪製模式和Charting模式做比對,找到一個平衡的設定。

如果你不知道如何設定,LightingTutorialOptimal這個範例場景可以當作是一個很好的參考,雖然大部分的情況下用預設值就可以得到很好的結果。

  • 嘗試使用不同的值來找出一個最低光照圖數量和失真度的平衡點
  • 複製設定,回到LightTutorialStart場景把設定貼回去所有的相同物件。選擇多個物件後能一次把設定貼上
  • 對Hierarchy視窗裡Structures目錄下所有的單獨命名的物件重複此步驟

一旦所有在Structures目錄下的物件都有了優化設定,可以轉到Rocks目錄下處理剩下的靜態物件。以這種手動循環設定好場景裡所有的靜態物件,確保有更好的迭代流程和更好的執行效能。

了解叢集

到目前為止我們已經圍繞在預計算即時GI的光照圖討論了很多像是縫合或打包技巧等等關於優化簡化光照圖的流程,這對減少預計算所產生的資料大小以及執行效能有很大的幫助。

接下來我們要討論的是叢集,透過修改叢集(Clusters)也是一個降低Unity預計算流程所需要執行的工作數量的好方法。降低叢集數量也能提高執行時的效能。

當採用PRGI來計算場景光照時,Unity會簡化產生一個立體像素化結構的計算,這些立體像素(Voxel)叫做叢集。叢集實際上是反映到場景靜態幾何表面用於照明的表面,叢集用一種層級關聯的結構來儲存,用來預計算Unity的全域光照漫反射所需要的複雜運算。雖然叢集和光照圖很像,但兩者用途是各自獨立的。
[转载]Unity5灯光GI烘焙优化插图29
Clustering繪製模式可以查看預計算GI所計算出的叢集大小

叢集會對靜態物件表面除去光照資料的材質(Albedo)進行取樣,然後在Light Transport運算階段計算這些叢集間的關聯,好讓光在整個叢集網之間傳遞。
Unity產生這種低解析度靜態環境,以便簡化在Runtime時需要更新的光照資料的量,在不同FPS的情況下透過硬體提供全域光照結果。
[转载]Unity5灯光GI烘焙优化插图30
圖示叢集X的值如何和附近的叢集值關聯(本圖由Geomerics提供)

一旦預計算完成後,你可以修改Skybox或光線的位置、強度和顏色,不需要再重新預計算,光線就會透過這些叢集網,連同場景材質和發光材質一併考慮計算光照反射。

第一次反彈之後的光照結果會被存回叢集裡,在每次的迭代後叢集會被採樣到相對應的光照貼圖裡,最後被場景Shader呼叫使用。

由於這個過程在CPU上非同步進行,每次的更新時間反映在用了多少工作執行緒,如果需要的話,可以從Lighting視窗找到CPU Usage來設定工作執行緒的多寡。
[转载]Unity5灯光GI烘焙优化插图31
Lit Clustering場景繪製模式下顯示出當光線透過叢集網反映到叢集的樣子

你可以用Clustering或Lit Clustering場景繪製模式來觀察叢集的分佈,在Clustering模式下,場景會由許多彩色方塊疊成一個診斷圖,每個正方形大小代表投射到靜態幾何的叢集大小,每一種顏色代表不同的叢集。Lit Clustering模式也是一樣,它顯示當光線透過叢集網並反映到叢集時的樣子。

降低叢集的數量在很大程度上決定了更新的速度,和在你目標平台的最終結果。更重要的是,這個教學的用意在說明當你減少叢集數量的設定將會加速預計算光照的時間,就結果來看,照明的迭代速度也會提升,下一章節會說明如何操作。

微調光照參數

Unity提供許多進階的光照貼圖控制方法,這些設定被放在一個光照參數集(Lightmap Parameters)的資源裡,好讓設定能在不同的專案場景或是透過版本控制和團隊一起共用。

  • 要建立一個Lightmap Parameters資源,先找到Project視窗
  • 從Create下拉選單建立(Create > Lightmap Parameters)
  • 我們也可以在Project介面裡按右鍵選(Asset > Create > Lightmap Parameters) 來建立。

[转载]Unity5灯光GI烘焙优化插图32
透過這個參數集可以針對烘焙光照或預計算GI做更高階的設定

建立完成的光照參數集可以被指定給靜態物件。

  • 從Hierarchy介面選擇你要指定變數集的物件,物件必須是帶有Mesh Renderer元件的靜態物件。
  • 開啟Lighting介面(Window > Lighting)並選擇Object頁籤
  • 從Advance Parameters下拉選單指定你的變數集給物件,右邊的"Edit"按鈕是開啟編輯光照變數的捷徑。

[转载]Unity5灯光GI烘焙优化插图33
從Lighting介面裡的Advanced Parameters欄位指定光照參數集

同一個光照參數集可以指定個許多不同的物件,你只要從Hierarchy介面一次把要指定的物件全選起來,執行上面說明的步驟把檔案指定到Advanced Parameters欄位即可。

光照參數集:實例(per-instance)還是預製(per-Prefab)好?

和拆UV的部分很像,光照參數集可以指定給Prefab預製物件或給場景裡的獨立物件,一旦參數集被貼上物件就會覆蓋掉物件身上舊有的設定。

這個方法的好處是你可以把正常情況下會用到的光照設定貼在預製物件上,然後依照不同需求修改覆蓋場景裡實例物件身上的光照參數設定。

本教學裡,我們會從一個實例物件身上示範如何使用光照參數集,主要是因為我們想根據使用的物件來選擇不同的光照參數集。

預設參數集

這部分適合用來設定場景預設的光照參數,這個參數集待會會被指定給所有場景裡面帶有Mesh Renderer元件但卻還沒指定Lightmap Parameters的物件。場景裡建立的任何帶有Mesh Renderer的物件都會以此為基礎,這樣可以省下手動指定的時間。

  • 開啟Lighting介面(Window > Lighting)並選擇Scene頁籤
  • 從General GI區塊裡找到Default Parameter,選擇你剛才建立的光照參數集。

雖然新的物件會開始採用這個預設設定值,你仍然可以從Advanced Parameter參數單讀覆蓋它。
[转载]Unity5灯光GI烘焙优化插图34
預設的設定會反映到所有新的靜態物件

Unity預設有幾組光照參數集可以選,分別是:

  • Default - HighResolution
  • Default - Medium
  • Default - LowResolution
  • Default - VeryLowResolution

這幾個不同的設定存有會影響到光照結果的設定像是光照貼圖解析度,光照圖大小以及其他一些進階選項設定,可以用來快速調整總體結果。

光照參數集說明

Unity預設的參數組合事實上已經很適合大多數的情況,但我們還可以建立自己的參數組並做更多的微調,來讓GI計算達到比預期更好的結果。

Unity手冊上關於光照參數集有個別的詳盡說明,但針對這個教學我們也會重點說明幾個最有用的設定。

Resolution

解析度的值確訂了物件採用的光照貼圖解析,這個值會和Lighting介面裡的解析度做加乘。比如說,如果場景解析度設為2,這裡的解析度設為0.5,那所有帶有這個參數集的物件都會採用1texel/unit來計算光照貼圖。

由於PRGI只會呈現場景裡的漫反射(diffuse)和間接照明,所以我們不需要用到像傳統烘焙貼圖那麼高(20-30)的採樣值,通常設定2-3已經很好了。如果是戶外場景,甚至可以縮小很多倍像是0.1就足以提供足夠的細節。
[转载]Unity5灯光GI烘焙优化插图35
解析度值很大光照貼圖所產生的影子斑點可以把Irradiance Budget這個參數調高來獲得緩解。

注意,當解析度值很大時,在較低解析度下可能會產生奇怪的陰影,這些陰影在最終的光照貼圖裡可能看起來像是斑點或髒汙。如果有這種情況可以試著把Irradiance Budget參數提高來獲得改善。

Cluster Resolution

叢集解析度用來決定1個像素裡能有多少叢集數量。假如這個值設為1,代表光照圖裡面每個像素都都會有一個叢集,0.5代表一個像素會有2個叢集,換句話說叢集會是光照圖的兩倍大。

進一步來說,可以想像如果我們把場景的解析度設為1,並建立一個1x1x1的方塊,然後指定這個光照參數集給物件,那麼方塊的每一面都會有1個叢集。如果我們把解析度改為2,結果就會變成2(1x1),方塊的每一面叢集會變成4個。
[转载]Unity5灯光GI烘焙优化插图36
上圖可以看到一個解析度設為1的1x1x1方塊,光照參數設定叢集解析度(Cluster Resolution)為1和光照貼圖解析度為2時,我們每一面都會有4個叢集。

在大多數的情況下,Cluster Resolution只需要設為低於貼圖像素(lightmap texels)大小即可,例如Default - HighResolution設定值為0.6。

一個場景中叢集太多的話會很快拉高預計算時間,還會影響到即時場景的光照效能,因此必須要把叢集的數量花在刀口上,永遠以保持品質儘可能的降低叢集數量為目標。

將光照貼圖解析和叢集解析度保持指定比例,這樣我們可以和場景整體的解析度建立一個相對關係。我們可以把Lighting介面裡面的解析度定義為高解析度作為整體設定,然後針對個別物件微調各自的光照參數集。

Unity採用這種分層法方便讓開發者能更全觀的控制場景光照,不然要針對每個物件手動都設定光照參數的值會很麻煩。

Irradiance Budget

我們之前說明過光照計算是如何用叢集來計算靜態物件的預計算光照,在預計算的過程裡,叢集之間的關係被建立起來,好讓光線得以在叢集網內快速傳遞。

在本質上,光照貼圖像素值的算法是基於叢集從該像素的位置對場景的一個檢視所計算得來,這會讓我們可以很快計算叢集之間的光照反射最後產生一個全域光照,這些叢集就能在畫面渲染完之前給予適當的樣本數。

Irradiance Budget(輻照度範圍)用來制訂當叢集採樣時每個光照貼圖像素所使用到的記憶體量,這會決定照明結果的精度,數值太低代表每個貼圖像素在記錄時使用較少記憶體同時提升CPU效能,代價就是會失真,數值越低光照結果會越模糊。反過來看,數值拉高GI會更準確,但記憶體和CPU的消耗都會提升。

如果我們的預計算在Runtime執行時更新有點慢或會lag,可能降低這個值會得到改善,這個設定比較適合用在不用精細的物件,很大、模糊或遙遠的物件。

Irradiance Quality

當計算PRGI時,每個光照貼圖像素會開始對場景投出射線,然後將可視資料報告給附近的叢集,然後貼圖像素就會得到每個叢集的百分比數值,這個值用來定義光照貼圖裡每個像素從叢集所分到的可視數據,而一欄設定就是用來設定每個像素能對場景投射多少射線。

如果場景裡的物件和周圍物件光照不合的情況下可以斟酌加大這個值,有時該暗的時候光照結果卻意想不到的亮,有可能是因為投射到場景的射線不足或遮擋到,導致漏算叢集資料。同樣該亮的的放如果射線沒有檢查到,可能會造成過暗。

提高射線的投射量就能解決類似的問題,代價就是增加預計算的時間,要優化這個時間,我們應該找出最適合的值來達到我們理想的照明效果。請注意,這個值不會影響到Runtime時的效能。

Backface Tolerance

當射線從光照貼圖像素投射出,從場景叢集蒐集光線時有時會打到幾何的背面,當計算全域光照時我們只需要關心投射到物體表面的光照,從背面來的光照資源通常都會忽略掉,這些從背面來的光照資料會破壞光照結果,因此調整這個值能防止這類情況發生。
[转载]Unity5灯光GI烘焙优化插图37
這裡的地板上的陰影就是Unity在計算期間從物件無效的背面所創造的,增加Backface Tolerance能改善這個問題。

Backface Tolerance必須指定從前方光源來的百分比,好讓正面的像素被判定為有效。假如一個貼圖像素沒通過測試,Unity會採用鄰近的像素值嘗試算得正確光照資料。

調整這個值並不會影響PRGI運算效能,也不會對預計算時間長度有太大影響。反而是蠻適合在調整Irradiance Budget都無法解決的場景貼圖太亮或太暗問題時,Backface tolerance會是一個不錯的除錯工具。

Modelling Tolerance

有時候在場景靜態物件中存在小間隙的區域會產生黑色的光暈或是不需要殘像,很容易發生在鄰近有相反幾何圖形的區域,像是地板上的物件:
[转载]Unity5灯光GI烘焙优化插图38
像這樣物品的黑暗邊緣通常可以透過加大Modelling Tolerance來改善

通常在這樣的情況下,物體和物體之間存在著小小的縫隙,因為沒有太多光線可以進入,導致非常暗的光照圖產生。當光照解析度低的時候,這些黑暗像素的大小可能會導致它們跑出遮擋物的邊界並產生不協調的黑色塊。

Modelling Tolerance是用來忽略比Threshold值還小的細節,提高這個值可以確保Unity 在計算GI時忽略掉非常靠近其他物體表面的幾何面,這個值越高代表Light Transport這個階段需要額外計算忽略這些間隙,調低Modelling Tolerance也能確保小物件不會被遺漏計算。

Modelling Tolerance不會影響PRGI的優化,對於計算時間和執行效能也沒甚麼負面影響,它能用在一些除錯流程上,解決連Irradiance Budget都無法改善的殘影問題。

開始建立Lightmap Parameters光照參數資源

現在我們已經明白光照參數能做甚麼了,可以開始嘗試建立這些資源。

  • 打開LightingTutorialStart場景
  • 在Project視窗找到Assets > LightmapParameters目錄並點進去
  • 從Project視窗最上面的下拉選單建立一個光照參數集(Create > Lightmap Parameters
  • 把物件名稱改為"TutorialTerrainLow"

[转载]Unity5灯光GI烘焙优化插图39
這個物件從鏡頭看起來非常大,蠻適合設一個光照參數集而不是用場景預設的

接下來我們要把剛剛新建的光照參數集指定給這個物件

  • 在場景視窗裡,選擇最接近主場景的兩座山,這些山都已經被命名為"MountainPeak"。注意,我們將忽略最遠的山。
  • 從Inspector介面確認兩個物件都是設定為靜態物件
  • 開啟Lighting視窗(Window > Lighting) 並選擇Scene頁籤
  • 確保最底下的Auto是打勾
  • 改選擇Object頁籤
  • 從Advanced Parameters下拉選單選擇剛建立的TutorialTerrainLow
  • 按一下右邊的Edit按鈕,準備開始調整設定

[转载]Unity5灯光GI烘焙优化插图40
預設的光照參數集

首先我們要看的是Resolution,降低這個值可以加速預計算時間同時也提升執行效能,所以我們應該目標定在不影響畫質的前提下採用較低的解析度。

會很接近看的物件可以設比較高的值,但是兩座山距離鏡頭都非常遠,因此這個例子設低一點是比較好的。這些大物件表面材質相當一致,從鏡頭的角度來看,接收到光的顏色變化也不大,所以可以降低這個值而不會影響結果品質。
[转载]Unity5灯光GI烘焙优化插图41
像是山或地形的大場景,採用預設值反而很浪費

[转载]Unity5灯光GI烘焙优化插图42
使用較低的解析度犧牲品質但可以大大節省預計算和執行效能

  • 慢慢的降低TutorialTerrainLow光照參數集裡面的Resolution參數並觀察結果的變化。

請記得這裡的解析度和Lighting視窗裡的場景解析度是會相乘的,目前場景解析度是1,代表如果這裡的解析度小於1的話,輸出的光照貼圖每unit也會小於1像素(texel)

兩座山和其他的物件距離非常遠,它們不可能接受頻率很高的光照,因此如果我們採用較低的解析度損失的品質不會太多。教學裡我們發現用0.05就足以採樣該有的光照資料。

  • 從Project視窗點選TutorialTerrainLow物件
  • 從Inspector介面把Resolution設為0.05

然後來看看Cluster Resolution的值,之前討論過,這個值也是一個用來和光照貼圖像素數量相乘計算叢集的乘法器,當數值是1的時候叢集的數量就等於光照貼圖像素的數量,因此低於1會比較好。叢集本質上是為了計算PRGI所產生類似靜態場景的模擬體,所以只有在數量不足以反映物體的光照反射時才需要加大這個值。

和光照貼圖解析很像,這兩座山的叢集解析度可以設很低,如果把它設的跟其他小場景一樣的話,代表可能會需要幾百個小場景的叢集量來覆蓋這兩座山。
[转载]Unity5灯光GI烘焙优化插图43

  • 對於很大的物件,叢集解析度可以設很低
  • 把Scene視窗左上方的繪製模式改為Clustering
  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Cluster Resolution的值慢慢降低,彩色色塊會慢慢變大,數量會慢慢變少

或是改用Lit Clustering繪製模式來評估設定的解析度是否足以採樣場景細節的光照。

  • 把Scene視窗左上方的繪製模式改為Lit Clustering
  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Cluster Resolution的值慢慢降低,觀察場景的變化。

調整到這裡時,可以問問自己是否能接受更低的叢集數值,如果繼續調高對畫質已經沒有好處了,那就應該要往下修正。請記住叢集數量對於預計算的時間和GI有很大的影響,這個案例我們發現用0.4是很適合的值。

  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 設定Cluster Resolution為0.4

[转载]Unity5灯光GI烘焙优化插图44
Lit Clustering繪製模式可以用來評估場景裡是否有足夠的叢集

需多情況下只是單單降低光照和叢集的解析度就足夠提升很大的效能,但是我們還能用Irradiance Budget和Irradiance Quality做更進一步的改進.

首先我們先看看Irradiance Budget,如之前所提,這個值控制貼圖像素會占用多少記憶體計算,為了執行時的效能,我們應該使用最低的值以免產生負面的影響。

如果預計算的結果模糊不清的話可以試著調大這個值,對於場景裡有著高對比度卻沒有被精確表達出來的區域是很有用的。
[转载]Unity5灯光GI烘焙优化插图45
Irradiance場景繪製模式可以用來評估調整Irradiance Budget或Quality的值

兩座山照明的頻率沒有很高,也沒有任何高對比的光照處理,代表在不影響品質的情況下,預設值128還能再低。

  • 把Scene視窗左上方的繪製模式改為Irradiance
  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Irradiance Budget的值慢慢降低
  • 你會看到當我們減少這裡的值時,兩座山上的照明會變得柔和一點

經過一些實驗之後,我們發現將Irradiance Budget設定為64最好

  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Irradiance Budget的值設為64

現在來看看另外一個Irradiance Quality,像之前所說的,Irradiance Quality影響著當計算光照像速時從叢集所投射出來的射線數量,不像Irradiance Budget只會影響到預計算時間,這個設定會影響到Runtime執行效能。

我們的兩座山是非常大的物件,代表不太容易錯過鄰近的叢集,因此我們可以透過降低Irradiance Quality來提升預計算的效能。

  • 把Scene視窗左上方的繪製模式改為Irradiance
  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Irradiance Quality的值慢慢降低
  • 隨著值的下降,產生的光照貼圖變得越來越模糊

我們發現2048是一個既可保持我們要的品質又能提升計算效能的平衡點,雖然準確對度會有點損失,但整體來看是利多於弊的。

  • 從Project視窗選擇TutorialTerrainLow光照參數集
  • 從Inspector介面裡把Irradiance Quality的值設為2048

把設定好的光照參數集指定給場景其他物件

現在我們可以幫LightingTutorialStart場景裡剩餘的靜態物件建立並指定光照參數集。

我們之前討論如果決定一個分類方法。基於特徵(例如大小或是距離鏡頭的距離)將場景物件分組,以方便我們能更容易為物件指定光照參數集。

當我們在處理Environment物件底下其餘的子物件時,請儘量幫能共享光照參數集的物件分同一類,例如:物件是否會很接近? 這樣如果提高該物件的解析度對於結果會明顯的改善,如果是很遠的物件你就不需要相同的設定值,如果物體材料無法反映材質的大量變化,高解析度就沒甚麼好處。

分組不需要太細,對於大多數情況下,幾組差異性大的設定就夠了,分太細也不好管理,可能每個細節都要針對物件獨立修改。

在我們完成的場景LightingTutorialOptimal裡面,我們分組依據如下:

  • RockLow:距離鏡頭有段距離的光滑石頭,因為距離遠所以解析度低。
  • RockMedium:光滑石頭,更接進玩家區域,所以需要高一點解析度和設定。
  • StructuresHigh:需要高解析度呈現的重要的建築物,同時也需要更高的Irradiance Budget和Quality設定。
  • StructuresLow:遠距離的建築物,只需要低解析度設定。
  • TerrainLow:大,遙遠的網格,比如山
  • TerrainPlayable:會很靠近鏡頭的大型地形,需要一個光照貼圖解析度來平衡,大的地形把叢集數量降低也還是很合理
  • TerrainVeryLow:非常遙遠和假的模擬地形,低解析度和低叢集數量,Irradiance Budget和Quality也都很低

除了這些自訂參數之外,在完成的教學LightingTutorialOptimal裡面,我們還放了一些使用預設光照參數的結構,這裡我們用預設的Default-Medium。

使用場景中大多數靜態物件預設的參數集可以減少很多手動的工作,將常用值指定為預設參數設定很有幫助,對於我們的目的,Default-Medium和預設1像素的解析度搭配使用很適合。
[转载]Unity5灯光GI烘焙优化插图46
Irradiance繪製模式用來評估場景照明非常有用,因為它只會顯示對PRGI有貢獻的靜態物件光照結果。

當要決定你的光照設定決策時,可以用LightingTutorialOptimal來當作一個評估基礎,將光照參數集指定給場景的物件不會花你太久的時間。記住,當你設定這些物件時,要不斷的思考調高參數值所帶來的好處有多少,如果調低帶來的負面影響不多,那不管如何都是首選。

總結

好比遊戲開發許多方面一樣,優化場景的用意就是希望在效能和視覺間找到一個完美的平衡,在許多狀況下,犧牲少量的畫質來加快預計算時間以及執行效能是很值得的。
[转载]Unity5灯光GI烘焙优化插图
一個有夜間照明處理的教學場景。處理好整個場景預計算之後就不需要額外計算不同時間的光照,這種技術對於傳統的烘焙光照是不可能達成的。

透過本次教學我們

  • 學習如何評估專案場景並決定適合的光照解析度
  • 了解光照圖,PRGI過程中最耗效能的元素之一,並學習如何降低它的數量。
  • 學習如何幫小物件設定光照探針。
  • 學習如何調整Unity的預計算參數,讓拆UV過程可以減少光照圖的數量。
  • 了解甚麼是叢集,如何使用與它對全域光照的影響。
  • 學習如何微調影響場景物件的光照貼圖變數,在不失真的情況下還能提高預計算效能。

將所有這些技術結合再一起就能讓你有效率的做出產品等級的場景,結合這種技術能快速迭代即時照明GI更新,加上即時改變照明反射的能力就可以做出很棒的作品。


版权所有:unity全球官方网站 原文地址:Introduction to Precomputed Realtime GI