首頁 遊戲資訊 從克勞德「黑臉」,說說為什...

從克勞德「黑臉」,說說為什麼需要全局光照

前言

實時渲染中的「實時(Realtime)」,指的是滿足每幀能完成畫面渲染任務,更多是一個性能指標概念,和是否真實沒直接關系。由於傳統渲染管線總歸是用一系列技術來近似真實世界的光照,所以如果出了Bug或全局光照設置不得當,就會出現標題畫面中的臉黑問題。

如果把物體表面直接著色稱為「直接光照」,與之對應的就是「間接光照」,兩者可以合稱全局光照。狹義的來劃分可以認為光線從光源直接照到物體表面並反射到攝像機的是直接光照,而彈射大於一次的光傳播效果都是間接光照。

次表面或一定體積的光照可以認為介於兩者之間,因為一定程度上已經需要模擬光線彈射幾次的結果了。

雖然概念上看著都是幾個字,但如果物體表面光照的實現難度好比溫順的小貓,次表面、體積光照的實現難度可能像是華南虎——而間接光照的實現就像是克蘇魯里的古神一樣,只提幾個概念就能產生大腦過載的感覺。

這篇文章可以認為是放在「遊戲中還原真實世界」的這個系列中,只是標題太長寫不下了。

大部分人包括我自己都還是寧可全局光照是一個黑盒,偶爾打開看一眼也要匆忙的關上,使其退化為引擎中不起眼的幾個選項和小按鈕。盡管如此,非光追渲染管線中能做到的全局光照特性還是不多,所以這次我會反著介紹——即先從光線追蹤的全局光照開始談起(先把大腦干超載了,把課題提出來,再逐步回收)。

從克勞德「黑臉」,說說為什麼需要全局光照

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中對比了只有直接光照和計算了一次彈射的全局光照的效果,後者會顯得明亮很多,因為計算中損失的能量更少)

1 基於光線追蹤的全局光照

一般認為光線追蹤(Ray Tracing)是一整套現代光傳播模式的渲染策略的集合,這里面大部分還是只能在離線渲染中使用。其基本思想其實已經反復提到了,但是實際技術方案中由於算力和采樣精度問題還是有一些優化點。

較好實現的光追可以覆蓋全局光照中的幾乎所有課題,因為已經盡可能模擬了物理世界中的光傳播——雖然精度可能永遠只能無限趨近。

1)光線追蹤—— Ray tracing [1979]

與後來的現代光線追蹤不同,最初的方案也被稱為Whitted style ray tracing。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中展示了1980年這一方案實現的折射和反射效果)

其基本策略仍是以射線的方式來計算,而不是以能量的方式來考慮衰減和光傳播。這一方案認為光線在光滑表面會彈射,在漫反射表面會停止彈射;由於在光滑表面彈射的原因,可以實現光滑表面的反射效果。

2)路徑追蹤—— Path tracing [1986]

基於輻射度量學(Radiometry)的思想,計算過程考慮能量在微表面的傳播與衰減。基於光路的可逆性,追蹤的既可能是光路也可能是攝像機視線。

基礎思想是從攝像機發射出射線,並基於蒙特卡洛積分方法(Monte Carlo integration)進行采樣——簡單的說就是把積分問題轉化為離散采樣問題,采樣策略和精度決定了結果的近似程度。

使用這種方法時,視線在每個物體表面還是只彈射出一次(這里與實際物理世界不完全一致),直到與光源連接或達到一定彈射次數。

這也是光線追蹤模式中的光源需要有體積的主要原因。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中是Wiki中Path Tracing實現的效果)

基於優化視線命中光源的效率問題,後續又提出了雙向路徑追蹤(Bidirectional Path Tracing)等方案。

3)其它更現代的光傳播計算策略

這里列舉一下,每個概念都不展開了。例如:光子映射(Photon mapping)、梅特波利斯光照傳輸(Metropolis light transport ),基本都是在光線追蹤的基礎上進行改進和特化。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中展示了光子映射用來解決酒杯的焦散渲染問題)

*從最早提出時間看,其實在離線渲染領域這些技術方案早就有了,只是遲遲無法應用到實時渲染領域。

2 實時渲染管線的全局光照技術概述

傳統渲染管線的全局光照,主要是基於預運算和螢幕空間的,後期還有一些基於3D空間體素化的方案(體素化後面的節會提到)。

由於是對物理世界的歸納和近似,對於物理世界中的一個特性都往往需要多種技術組合實現。

1)整體顏色問題——環境光、烘焙光照貼圖

傳統的環境光指按一定策略為范圍內的物體統一疊加某種顏色,可以動態調整(室內、室外切換之類)。烘焙則顧名思義不可動態變化。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中展示了Unity中的烘焙光照貼圖)

2)明暗問題——包括實時陰影、烘焙陰影、實時AO、烘焙AO(關於AO下一節會談到)等

陰影和環境光遮蔽(AO)更多的是人為劃分,因為傳統管線里無法為所有物體都計算所有光源的實時光照明暗。

可以簡單認為直接光照未能照亮的部分稱為陰影(包含軟陰影與自陰影問題),這部分主要是通過陰影貼圖(ShadowMap)的一系列技術來實現。對於多光源的陰影還引入了反射陰影貼圖(RSV——Reflective Shadow Mapping)技術,這里不展開了。

間接光照渲染時,環境中中較暗的部分則被稱為AO。實際實現中往往通過不同物體表面連接處的接近閉合程度來近似計算。

3)反射問題——主要思路是實時反射(攝像機或Ray Marching)和從預渲染圖中反射(之前一篇講鏡面反射的文章中寫了很多)

4)間接光照問題——在非光追管線中想實時的來模擬光線彈射後照到物體的效果,主要包含螢幕空間和3D空間這兩大方向

5)其它輔助效果——每項都是對物理世界中一類效果的還原,屬於對光照系統的補充。例如鏡頭光暈(Lens flare)效果、霧效果、水體焦散(Caustics)、體積光照(典型的如丁達爾效應 The Tyndall effect )等。

3 環境光遮蔽概述

環境光遮蔽(AO—— Ambient Occlusion)在美術上也被稱為閉合陰影。基本設想是物體表面越接近越封閉的部分受光越少,因此可以基於物體之間的接近和封閉程度來推算間接光照的明暗。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中是Large Scale Ambient Occlusion的中間件效果展示,第二行是開啟了AO的效果。右邊的屋內也是一類典型的間接光照場景)

看圖基本能理解為什麼需要AO。這里介紹兩類實時AO的方案:

1)螢幕空間AO(SSAO——Screen Space Ambient Occlusion)

SSAO指運用幀緩沖中的有效數據進行AO推算的一類技術,其主要計算依據是緩沖區中的深度和法線貼圖。結合這兩者,通過一些采樣策略來近似估計得到某個著色點的AO值。

從克勞德「黑臉」,說說為什麼需要全局光照

(Wiki中SSAO的傳統流程,對於一些極限值是需要引入偏移量來修正的)

後續還疊代出了改進版本的HBAO( Horizon-Based AO),這里不展開了。

2)體積AO(AO Volume)

其基本思想是為動態計算AO的物體預計算其各方向的遮擋采樣情況,存儲為一個空間貼圖(Volume Texture)。其中的指可以預覽為空間中環繞物體的很多錐體,包含——方向、位置、錐立體角度幾個信息維度。

渲染時,空間中的任何一個接近物體AO計算范圍的著色點,都可以帶入這個預存儲數據計算,得到一個近似的AO值。當然實際應用中還需要調一些魔鬼數字的函數偏移量(Bias),畢竟這是一個trick。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中展示了這一方案預存儲數據的預覽效果)

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中顯示了這一方案添加了Bias後的實時渲染效果)

這個方案可以解決的典型的一類問題就是人物爬牆過程的實時AO計算(這里指的不是陰影,而是間接光照產生的AO)。

4 球諧函數及其應用

球諧光照是一種基於球諧函數(Spherical Harmonics, SH)的著色算法,它用於模擬低頻的環境光照明。實時渲染中通常使用低階球諧函數來編碼存儲光照信息,這些函數可以查詢球面上不同方向(位置)的光照顏色值。

實際執行時先對復雜光源進行預采樣,把結果保存到一些球諧光采樣器中,在實時渲染時就可以通過著色點在空間中的位置帶入函數得到顏色值——多個采樣點之間可以通過權重和插值之類方式混合。

采樣為球諧光照數據的過程可以視為進行了一次有損壓縮,但優勢是實際要存的值相對很少(RGB共27個係數)。

這個方案對於低頻信號近似效果較好;而反射光和高光屬於高頻,無法被涵蓋在這個方案中。

在我比較熟悉的Unity中,就有光探針(Ligth Probe)方案:

從克勞德「黑臉」,說說為什麼需要全局光照

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中的動態物體在運行時可以依據光探針組改變其表面的光照著色)

5 體素及其應用

體素(Voxel)是實時渲染中一種常用的中間結構,是一種把空間中物體顏色插值歸納成「大顆粒」的立方體——體素,便於做實時近似采樣的技術。體素准確的說是一種顏色查找結構,只是預覽時會表現為大的立方體。對於靜態場景,相關的體素查找結構都是可以預計算的。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中的顏色方塊就是體素的預覽效果)

這里列舉2種在利用體素思想在3D空間中實現全局光照的方案:

1)光傳播體積(LPV ——Light Propagation Volutions)

核心思路就是將空間網格(體素)化,把計算過直接光照的表面作為一次彈射起點,然後發出射線在擊中的體素上采樣計算,作為間接光照的結果。

由於存儲和查找時是需要通過球諧函數(SH),所以速度相對快;但這個方案只能處理好漫反射表面的間接光照,並由於其精度的損失會帶來漏光問題。

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中的間接光照部分採用的就是LPV方案)

2)體素全局光照(VXGI—— Voxel Global Illumination)

與前者不同是這套方案是把幾何物體網格(體素)化。預計算時將網格體素離散化為樹狀結構並存儲光照計算相關信息,在渲染時通過錐體追蹤(Cone Tracing)來計算光照 。

由於有了多層樹狀結構和錐體追蹤,因此用更多存儲空間和性能消耗換來了相對更高的精度。這2個方案的對照也可以近似理解為一層紋理和多層Mipmap之間的關系(雖然有一些查找策略等細節完全不同)。

從克勞德「黑臉」,說說為什麼需要全局光照

從克勞德「黑臉」,說說為什麼需要全局光照

(圖中展示了這一方案通過2個Pass實現預運算和查找的思路)

相關的更學術化的講解都可以從Games202系列課中找到,這里只是粗略的介紹了這套方法的概念聯系。

結語

本文粗淺地介紹了一下全局光照,可以看出這個概念是由一堆不斷疊代的技術方案來組成的。即便遊戲有很高的渲染精度,也用上了虛幻引擎,並不意味著這種需要一事一議的全局光照就能一勞永逸的快速搞定了。引擎的好效果只是其上限,至於如何發揮出上限還需要積累漫長的優化和美化經驗。

很多全局光照技術如果需要用在風格化渲染(如卡通渲染)中,都需要定製化的進行改進;而且光線追蹤也不是風格化渲染的通解。

另外還是一個老生常談的問題,就是即使在幾年後的次時代主機上,只用光追管線的時代還遠遠無法到來。類似《墮落之主》《奇喚士》這類畫風偏寫實的准3A遊戲,還是必須打開全局光照這個愁人的潘多拉魔盒。

最後是一些資料連結:

Ray Tracing Wiki

Ambient Occlusion Wiki

SSAO Wiki

體積AO的GDC連結

球諧函數Wiki

球諧光照的Paper

CryEngine3中的LPV

來源:機核