1. 程式人生 > >【《Real-Time Rendering 3rd》 提煉總結】(八) 第九章 · 全域性光照:光線追蹤、路徑追蹤與GI技術進化編年史

【《Real-Time Rendering 3rd》 提煉總結】(八) 第九章 · 全域性光照:光線追蹤、路徑追蹤與GI技術進化編年史

全域性光照(Global Illumination,簡稱 GI), 作為圖形學中比較酷的概念之一,是指既考慮場景中來自光源的直接光照,又考慮經過場景中其他物體反射後的間接光照的一種渲染技術。

大家常聽到的光線追蹤,路徑追蹤等同樣很酷的概念,都是全域性光照中人氣較高的演算法流派。

而這篇文章將圍繞全域性光照技術,介紹的要點有:

  • 全域性光照的基本概念
  • 全域性光照的演算法主要流派
  • 全域性光照技術進化編年史
  • 光線追蹤 Ray Tracing
  • 路徑追蹤 Path Tracing
  • 光線追蹤、路徑追蹤、光線投射的區別
  • 環境光遮蔽 Ambient Occlusion

一、行文思路說明

閱讀過《Real-Time Rendering 3rd》第九章的讀者們都會發現,作為一章關於全域性光照的章節,作者講了不少在嚴格意義上全域性光照主線以外的內容,如Reflections、Refractions、Shadow等節,而這些內容在《Real-Time Rendering 2nd》中,其實是放在Chapter 6 Advanced Lighting and Shading一節的。

既然《Real-Time Rendering 3rd》第九章標題就叫全域性光照,核心內容也是全域性光照,本文即決定脫離原書安排的100來頁的多餘內容,以全域性光照的主線內容為主,構成一篇包含全域性光照基本概念,主要演算法流派,以及全域性光照技術進化編年史,和全域性光照演算法中人氣較高的光線追蹤、路徑追蹤等演算法的綜述式文章。

二、全域性光照

全域性光照,(Global Illumination,簡稱 GI), 或被稱為Indirect Illumination, 間接光照,是指既考慮場景中直接來自光源的光照(Direct Light)又考慮經過場景中其他物體反射後的光照(Indirect Light)的一種渲染技術。使用全域性光照能夠有效地增強場景的真實感。

即可以理解為:全域性光照 = 直接光照(Direct Light) + 間接光照(Indirect Light)


圖1 Direct illumination

 

圖2 Global illumination = Direct illumination +Indirect illumination

上述兩幅圖片來自CMU 15-462/15-662, Fall 2015 Slider,Lecture 14: Global Illumination,當然,細心的朋友也可以發現,它也被《Physically Based Rendering,Second Edition From Theory To Implementation》選作封面。

 可以發現,加入了Indirect illumination的圖2,在直接光源(陽光)照射不到的地方,得到了更好的亮度和細節表現,從而使整張渲染效果更具真實感。

雖說實際應用中只有漫反射全域性照明的模擬演算法被稱為全域性照明演算法,但其實理論上說反射、折射、陰影都屬於全域性光照的範疇,因為模擬它們的時候不僅僅要考慮光源對物體的直接作用還要考慮物體與物體之間的相互作用。也是因為,鏡面反射、折射、陰影一般不需要進行復雜的光照方程求解,也不需要進行迭代的計算。因此,這些部分的演算法已經十分高效,甚至可以做到實時。不同於鏡面反射,光的漫反射表面反彈時的方向是近似“隨機”,因此不能用簡單的光線跟蹤得到反射的結果,往往需要利用多種方法進行多次迭代,直到光能分佈達到一個基本平衡的狀態。

三、全域性光照的主要演算法流派

經過幾十年的發展,全域性光照現今已有多種實現方向,常見的全域性光照主要流派列舉如下:

  • Ray tracing 光線追蹤
  • Path tracing 路徑追蹤
  • Photon mapping 光子對映
  • Point Based Global Illumination 基於點的全域性光照
  • Radiosity 輻射度
  • Metropolis light transport 梅特波利斯光照傳輸
  • Spherical harmonic lighting 球諧光照
  • Ambient occlusion 環境光遮蔽
  • Voxel-based Global Illumination 基於體素的全域性光照
  • Light Propagation Volumes Global Illumination
  • Deferred Radiance Transfer Global Illumination
  • Deep G-Buffer based Global Illumination
  • 等。

而其中的每種流派,又可以劃分為N種改進和衍生演算法。

如光線追蹤(Ray Tracing)派系,其實就是一個框架,符合條件的都可稱為光線追蹤,其又分為遞迴式光線追蹤(Whitted-style Ray Tracing),分散式光線追蹤(DistributionRay Tracing),蒙特卡洛光線追蹤(Monte Carlo Ray Tracing)等。

而路徑追蹤(Path tracing)派系,又分為蒙特卡洛路徑追蹤(Monte Carlo Path Tracing),雙向路徑追蹤(BidirectionalPath Tracing),能量再分配路徑追蹤(Energy Redistribution PathTracing)等。

其中有些派系又相互關聯,如路徑追蹤,就是基於光線追蹤,結合了蒙特卡洛方法而成的一種新的派系。

四、全域性光照技術進化編年史

這節以光線追蹤和路徑追蹤派系為視角,簡單總結一下全域性光照技術發展早期(1968-1997)的重要里程碑。

4.1 光線投射 Ray Casting [1968]

光線投射(Ray Casting),作為光線追蹤演算法中的第一步,其理念起源於1968年,由Arthur Appel在一篇名為《 Some techniques for shading machine rendering of solids》的文章中提出。其具體思路是從每一個畫素射出一條射線,然後找到最接近的物體擋住射線的路徑,而視平面上每個畫素的顏色取決於從可見光表面產生的亮度。

 

圖3 光線投射:每畫素從眼睛投射射線到場景

4.2 光線追蹤 Ray Tracing [1979]

1979年,Turner Whitted在光線投射的基礎上,加入光與物體表面的互動,讓光線在物體表面沿著反射,折射以及散射方式上繼續傳播,直到與光源相交。這一方法後來也被稱為經典光線跟蹤方法、遞迴式光線追蹤(Recursive Ray Tracing)方法,或 Whitted-style 光線跟蹤方法。光線追蹤方法主要思想是從視點向成像平面上的像素髮射光線,找到與該光線相交的最近物體的交點,如果該點處的表面是散射面,則計算光源直接照射該點產生的顏色;如果該點處表面是鏡面或折射面,則繼續向反射或折射方向跟蹤另一條光線,如此遞迴下去,直到光線逃逸出場景或達到設定的最大遞迴深度。


圖4 經典的光線追蹤: 每畫素從眼睛投射射線到場景,並追蹤次級光線((shadow, reflection, refraction),並結合遞迴

4.3 分散式光線追蹤 Distributed Ray Tracing [1984]

Cook於1984年引入蒙特卡洛方法(Monte Carlo method)到光線跟蹤領域,將經典的光線跟蹤方法擴充套件為分散式光線跟蹤演算法(Distributed Ray Tracing),又稱為隨機光線追蹤(stochasticray tracing),可以模擬更多的效果,如金屬光澤、軟陰影、景深( Depthof Field)、運動模糊等等。

4.4 渲染方程 The Rendering Equation [1986]

在前人的研究基礎上,Kajiya於1986年進一步建立了渲染方程的理論,並使用它來解釋光能傳輸的產生的各種現象。這一方程描述了場景中光能傳輸達到穩定狀態以後,物體表面某個點在某個方向上的輻射率(Radiance)與入射輻射亮度等的關係。

可以將渲染方程理解為全域性光照演算法的基礎,Kajiya在1986年第一次將渲染方程引入圖形學後,隨後出現的很多全域性光照的演算法,都是以渲染方程為基礎,對其進行簡化的求解,以達到優化效能的目的。渲染方程根據光的物理學原理,以及能量守恆定律,完美地描述了光能在場景中的傳播。很多真實感渲染技術都是對它的一個近似。渲染方程在數學上的表示如下:

                                      


圖5 渲染方程描述了從x點沿某一方向看的光放射的總額。

4.5 路徑追蹤 Path Tracing [1986]

Kajiya也於1986年提出了路徑追蹤演算法的理念,開創了基於蒙特卡洛的全域性光照這一領域。根據渲染方程, Kajiya 提出的路徑追蹤方法是第一個無偏(Unbiased)的渲染方法。路徑追蹤的基本思想是從視點發出一條光線,光線與物體表面相交時根據表面的材質屬性繼續取樣一個方向,發出另一條光線,如此迭代,直到光線打到光源上(或逃逸出場景),然後用蒙特卡洛的方法,計算其貢獻,作為畫素的顏色值。

4.6 雙向路徑追蹤 Bidirectional Path Tracing [1993,1994]

雙向路徑追蹤(Bidirectional Path Tracing)的基本思想是同時從視點、光源打出射線,經過若干次反彈後,將視點子路徑( eye path) 和光源子路徑( light path) 上的頂點連線起來(連線時需要測試可見性),以快速產生很多路徑。這種方法能夠產生一些傳統路徑追蹤難以取樣到的光路,所以能夠很有效地降低噪聲。 進一步的, [Veach 1997]將渲染方程改寫成對路徑積分的形式,允許多種路徑取樣的方法來求解該積分。

4.7 梅特波利斯光照傳輸 Metropolis Light Transport [1997]

Eric Veach等人於1997年提出了梅特波利斯光照傳輸(Metropolis Light Transport,常被簡稱為MLT)方法。路徑追蹤( Path Tracing)中一個核心問題就是怎樣去儘可能多的取樣一些貢獻大的路徑,而該方法可以自適應的生成貢獻大的路徑,簡單來說它會避開貢獻小的路徑,而在貢獻大的路徑附近做更多區域性的探索,通過特殊的變異方法,生成一些新的路徑,這些區域性的路徑的貢獻往往也很高。 與雙向路徑追蹤相比, MLT 更加魯棒,能處理各種複雜的場景。比如說整個場景只通過門縫透進來的間接光照亮,此時傳統的路徑追蹤方法因為難以取樣到透過門縫的這樣的特殊路徑而產生非常大的噪聲。

五、光線追蹤 Ray Tracing

光線追蹤(Ray tracing)是三維計算機圖形學中的特殊渲染演算法,跟蹤從眼睛發出的光線而不是光源發出的光線,通過這樣一項技術生成編排好的場景的數學模型顯現出來。這樣得到的結果類似於光線投射與掃描線渲染方法的結果,但是這種方法有更好的光學效果,例如對於反射與折射有更準確的模擬效果,並且效率非常高,所以當追求高質量的效果時經常使用這種方法。

上文已經提到過,Whitted於1979年提出了使用光線跟蹤來在計算機上生成影象的方法,這一方法後來也被稱為經典光線跟蹤方法、遞迴式光線追蹤方法,或 Whitted-style 光線跟蹤方法。其主要思想是從視點向成像平面上的像素髮射光線,找到與該光線相交的最近物體的交點,如果該點處的表面是散射面,則計算光源直接照射該點產生的顏色;如果該點處表面是鏡面或折射面,則繼續向反射或折射方向跟蹤另一條光線,如此遞迴下去,直到光線逃逸出場景或達到設定的最大遞迴深度。

以下這張圖示可以很好的說明光線追蹤方法的思路:


圖6 Ray Tracing Illustration First Bounce


圖7 光線追蹤渲染出的效果圖1


圖8 光線追蹤渲染出的效果圖2


圖9 光線追蹤渲染效果圖 @Caustic-Graphics,Inc


圖10 典型的光線追蹤渲染效果圖

光線跟蹤的一個最大的缺點就是效能,需要的計算量非常巨大,以至於目前的硬體很難滿足實時光線追蹤的需求。傳統的光柵圖形學中的演算法,利用了資料的一致性從而在畫素之間共享計算,但是光線跟蹤通常是將每條光線當作獨立的光線,每次都要重新計算。但是,這種獨立的做法也有一些其它的優點,例如可以使用更多的光線以抗混疊現象,並且在需要的時候可以提高影象質量。儘管它正確地處理了相互反射的現象以及折射等光學效果,但是傳統的光線跟蹤並不一定是真實效果影象,只有在非常近似或者完全實現渲染方程的時候才能實現真正的真實效果影象。由於渲染方程描述了每個光束的物理效果,所以實現渲染方程可以得到真正的真實效果,但是,考慮到所需要的計算資源,這通常是無法實現的。於是,所有可以實現的渲染模型都必須是渲染方程的近似,而光線跟蹤就不一定是最為可行的方法。包括光子對映在內的一些方法,都是依據光線跟蹤實現一部分演算法,但是可以得到更好的效果。

用一套光線追蹤的虛擬碼,結束這一節的介紹:

[cpp] view plain copy print?
  1. for each pixel of the screen  
  2. {  
  3.     Final color = 0;  
  4.         Ray = { starting point, direction };  
  5.         Repeat  
  6.     {  
  7.         for each object in the scene  
  8.             {  
  9.                     determine closest ray object/intersection;  
  10.             }  
  11.         if intersection exists  
  12.         {  
  13.                 for each light inthe scene  
  14.                 {  
  15.                         if the light is not in shadow of anotherobject  
  16.                         {  
  17.                             addthis light contribution to computed color;  
  18.                         }  
  19.         }  
  20.     }  
  21.         Final color = Final color + computed color  previous reflectionfactor;  
  22.         reflection factor = reflection factor  surface reflectionproperty;  
  23.         increment depth;  
  24.       } until reflection factor is 0 or maximumdepth is reached  
  25. }  
for each pixel of the screen 
{
Final color = 0;
Ray = { starting point, direction };
Repeat
{
for each object in the scene
{
determine closest ray object/intersection;
}
if intersection exists
{
for each light inthe scene
{
if the light is not in shadow of anotherobject
{
addthis light contribution to computed color;
}
}
}
Final color = Final color + computed color * previous reflectionfactor;
reflection factor = reflection factor * surface reflectionproperty;
increment depth;
} until reflection factor is 0 or maximumdepth is reached
}

六、路徑追蹤 Rath Tracing

路徑追蹤(Rath Tracing)方法由Kajiya在1986年提出,是第一個無偏(Unbiased)的渲染方法。

路徑追蹤方法的基本思想是從視點發出一條光線,光線與物體表面相交時根據表面的材質屬性繼續取樣一個方向,發出另一條光線,如此迭代,直到光線打到光源上(或逃逸出場景),然後用蒙特卡洛方法,計算光線的貢獻,作為畫素的顏色值。而使用蒙特卡洛方法對積分的求解是無偏的,只要時間足夠長,最終影象能收斂到一個正確的結果。

簡單來說,路徑追蹤 = 光線追蹤+ 蒙特卡洛方法。

這裡有一個用99行程式碼實現路徑追蹤演算法的一個簡易全域性光照渲染器,有興趣的朋友可以進行了解:

 

圖11 基於路徑追蹤渲染的效果圖


圖12 基於路徑追蹤實現的次表面散射渲染效果圖  ©Photorealizer

 

 

圖14 基於路徑追蹤渲染的效果圖 ©NVIDIA

七、Ray Casting , Ray Tracing,PathTracing區別

初學者往往會弄不明白光線投射(Ray Casting ),光線追蹤(Ray Tracing),路徑追蹤(Path Tracing)三者的的區別,龔大@龔敏敏 在https://www.zhihu.com/question/29863225這個答案中的回答已經很精闢,本文就直接引用了過來:

  • Ray Tracing:這其實是個框架,而不是個方法。符合這個框架的都叫raytracing。這個框架就是從視點發射ray,與物體相交就根據規則反射、折射或吸收。遇到光源或者走太遠就停住。一般來說運算量不小。
  • Ray Casting:其實這個和volumetric可以脫鉤。它就是ray tracing的第一步,發射光線,與物體相交。這個可以做的很快,在Doom 1裡用它來做遮擋。
  • Path Tracing:是ray tracing + 蒙特卡洛法。在相交後會選一個隨機方向繼續跟蹤,並根據BRDF計算顏色。運算量也不小。還有一些小分類,比如Bidirectional path tracing。

文末,簡單聊一下環境光遮蔽,AO。

八、環境光遮蔽 Ambient Occlusion

環境光遮蔽(Ambient Occlusion,簡稱AO)是全域性光照明的一種近似替代品,可以產生重要的視覺明暗效果,通過描繪物體之間由於遮擋而產生的陰影, 能夠更好地捕捉到場景中的細節,可以解決漏光,陰影漂浮等問題,改善場景中角落、鋸齒、裂縫等細小物體陰影不清

晰等問題,增強場景的深度和立體感。

可以說,AO 特效在直觀上給玩家的主要感覺體現在畫面的明暗程度上,未開啟 AO 特效的畫面光照稍亮一些;而開啟環境光遮蔽特效之後, 區域性的細節畫面尤其是暗部陰影會更加明顯一些。

Ambient Occlusion的細分種類有:

  • SSAO-Screen space ambient occlusion
  • SSDO-Screen space directional occlusion
  • HDAO-High Definition Ambient Occlusion
  • HBAO+-Horizon Based Ambient Occlusion+
  • AAO-Alchemy Ambient Occlusion
  • ABAO-Angle Based Ambient Occlusion
  • PBAO
  • VXAO-Voxel Accelerated Ambient Occlusion

一般而言,Ambient Occlusion最常用方法是SSAO,如Unreal Engine 4中的AO,即是用SSAO實現。

接下來貼一些和AO相關的圖,結束這篇文章。


圖15 Scene without Ambient Occlusion  ©NVIDIA

 

圖16 Ambient Occlusion Only


圖17 Scene with Ambient Occlusion

 

圖18 使用環境光遮蔽製作人物的步驟


圖19 一張典型的環境光遮蔽的渲染圖

圖20 有無環境光遮蔽渲染效果對比圖示

九、其他參考