本文目錄如下。

PBR中基於影象的光照

PBR的間接光照(基於影象的光照)

關於環境貼圖

IBL 漫反射

IBL 鏡面反射

感謝Epic games!

術語:

注意

: 經過組裡幾次討論後,我發現在第一篇帖文中沒有解釋清楚一些要點。我已經在前文中更新了關於如何處理金屬度和鏡面反射的內容,希望你們有時間看一下。

PBR中基於影象的光照

在[譯] 面向美術師的基於物理的渲染(PBR)指南 _2 中,我討論了針對開發者的PBR基礎知識,並解釋了PBR光照流程的步驟。

如前所述,PBR不一定意味著要有間接光照,但為了讓效果更好看,間接光照會起到錦上添花的作用。今天,我會重點介紹基於影象的光照(IBL)技術,這是一種廉價計算間接光照的方法。如前文一樣,你們可在文章結尾處找到術語表,用以解釋術語定義。

利用IBL的PBR間接光照

直接光照是一種常見的光源,大家應該很熟悉(點光,定向光……)。但可能對間接光照會相對生疏一些。首先,你需要弄懂我們想要模擬什麼樣的間接光照。

通常,它是指全域性光照(或GI)。指光線反彈至周邊物體,照亮著色的表面。實現全域性光照的技術有幾種,但是最常見的是基於影象的光照(IBL)。一般和PBR工作流程緊密相關。

所以,基本上游戲中的光源是一種顏色,也可選擇其他引數,如方向、位置、半徑等等……一張影象有顏色資訊,它的顏色可被視為光源。全域性光照的光線來自四面八方,有一個好辦法來用IBL模擬GI,即把環境貼圖作為光源處理。

關於環境貼圖:

大多情況下,遊戲中的環境貼圖都是立方體貼圖(cubemap)。

我們如何取樣環境貼圖呢?使用視線方向相對於著色表面的反射向量,也就是我們通常所說的反射向量。一圖勝千語。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

出自維基百科 : TopherTH at the English language Wikipedia [GFDL (http://www。gnu。org/copyleft/fdl。html), GFDL (http://www。gnu。org/copyleft/fdl。html) or CC-BY-SA-3。0 (http://creativecommons。org/licenses/by-sa/3。0/)], via Wikimedia Commons Here the reflected Ray is our reflection ve

上圖中的反射線就是反射向量。

糟糕的是,我們不能把它們當做直接光源一樣來處理,在環境貼圖上拾取每個畫素點來計算光線,只能期待能得到最好的結果。老實說,我沒搞懂這裡面的數學計算。我在這裡不會解釋很難懂的數學公式,直切正題:如何從環境貼圖中計算光照。

IBL漫反射

首先,我們需要計算來自環境貼圖的漫反射因子。還記得前文提到的漫反射BRDF嗎?

蘭伯特Lambert

光照模型。

簡單來說,Lambert漫反射BRDF是用在遊戲中的,它是一個光線顏色乘以一個可見度引數。這個可見性引數是著色幾何體法線和光線方向的函式。

假設有一個直接光源照亮幾何體的正面,那幾何體的背面就是暗的。這意味著幾何體正面的可見度強度是1,而背面可見度強度是0。而對於間接光照,因為光線是來自四面八方的,我們可以忽略這些可見度引數。那麼,所有這些就能簡化成漫反射因子=光線顏色。

但是,給定點的光線顏色是什麼呢?從技術上來說,環境貼圖中的每個畫素點都是一個光源,那麼一個著色點(shaded point)會被大量的畫素照亮。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

如上圖所示,橙色區域代表從立方體貼圖(cubemap)到著色畫素點的光線,我們得考慮合理地計算出燈光顏色。即,每個著色畫素點要拾取所有的紋素併合並顏色。

其實這在實時渲染工作流中是不可行的。即便是一張128x128的環境貼圖,會有將近50k紋理拾取每個畫素。所幸,我們可以使用輻照度貼圖。一張輻照度貼圖基本能負荷剛提到的計算量……但需要預計算,並將結果烘焙至紋理中。下圖是一張輻照度貼圖。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

左圖是原始立方體貼圖(cubemap),右圖是預計算的輻照度貼圖。

所以在執行時,你只需取樣一次反射向量。很酷吧,Aha?除開我們在預計算貼圖時,仍需要取樣cubemap數十億次這點,即使是在編輯階段……也會耗費很長一段時間。

球諧函式(SH)

這又是什麼?我不會做詳細解釋(因為解釋不了;-P),我知道這又是一個大名鼎鼎的神奇數學魔法。我會用簡單的文字來解釋你可以用這個函式幹什麼。

簡單來說,球諧函式能幫助我們更快地計算出輻照度貼圖。總結起來就是:只需計算9個球諧係數便可高效地近似出一個輻照因子。此時,你甚至可以跳過預計算輻照度貼圖,直接在shader中用畫素著色器的方式使用這些係數。這對於實時渲染來說足夠快了,而且記憶體也比cubemap更少。但……它依然比取樣一次要慢,所以我選擇計算輻照度貼圖,將它用於著色器中。

透過這種技術,我可以在200ms內,在Java的CPU上計算一張128x128輻照度貼圖。雖然每一幀的處理上非常慢,但在編輯階段就是一眨眼的事。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

上圖為使用輻照度貼圖,材質受間接光照的漫反射影響。

IBL 鏡面反射

間接漫反射挺酷的,但是我們還要“閃亮”的效果!!閃亮就意味著鏡面反射光照。

明確我們想要怎樣的鏡面反射,這一點很重要。我們想要粗糙度低時,鏡面反射清晰;反之,粗糙度高時反射要模糊。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

隨著粗糙度越高,鏡面反射則越模糊。

為此,我們必須解析

輻射積分

有一個辦法能非常快速地處理,即

重要取樣法(importance sampling)

。但這個方法要求大量的取樣方能獲得正確的結果,所以速度非常慢。舉個例子,在之前那個鏡頭中我使用了這種方法,取樣1024次。因為它在GTX 670上跑16幀,所以幾乎沒有互動的體驗。

感謝Epic!

針對這個問題,虛幻引擎4提出瞭解決方案。其實其他引擎也有做,但Epic的Brian Karis將方法公開於眾了,感謝!

在這篇 論文中,Epic解釋了UE4中的處理方式。他們的解決辦法叫做

分解求和近似(Split Sum Approximation)

。該方法不會加速計算,但會將其進行轉換,以便將它烘焙成兩個預過濾(prefiltered)的紋理。

預過濾(prefiltered)的環境貼圖

我們準備在CPU上預處理一張環境貼圖。

如前所述,我們想要粗糙度越高,反射越模糊的效果。這裡的主要思路是在環境貼圖mipmap中儲存不同層級的粗糙度。第一層mipmap的粗糙度是0,最後一層的粗糙度是1。從mip到mip層級間,我們將根據粗糙度對影象進行卷積(模糊)處理。粗糙度越高,取樣的次數越多,光線分散得就越厲害。

還沒結束,我們還想要在貼圖中“烘焙”鏡面反射BRDF,所以對於每個畫素,我們將計算Cook-Torrentz microfacet BRDF(前文)。但因為我們是預處理貼圖,沒有任何關於著色表面法線和視線方向的資訊。所以我們假設他們都是一樣的,並等於環境向量,從貼圖中取樣,並且假設著色點恰好位於立方體貼圖(cube map)的中心。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

這又是一個近似,在質量上也有開銷。但我們還是都想要近似,因為它執行快,而且效果看上去不錯,aha?下圖為效果圖。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

擁有不同mip層級的預過濾(prefiltered)環境貼圖。請注意模糊用它們是如何增強的。

所以,我們可以用一個紋理取樣來評估第一個分解求和近似的和。我們將根據粗糙度計算Lod層級(獲取紋素的mip層)。請注意,為了在紋理立方體(texture cube)和mipmap之間做線性插值,要設定好影象,所以如果粗糙度值在mip層級上不正確,它就會在兩個最近的mip層間插值。

BRDF整合圖

現在我們需要求第二個分解求和近似的和。

它是一個積分,有2個輸入,

粗糙度

範圍是0-1,法線和光線方向的點積(

N.L

, 讀作N dot L)範圍也是0-1。輸出量是1個

縮放(scale)

和1個

偏移(bias)

,範圍介於0-1之間。

所以基本上我們可以將所有組合烘焙至2D貼圖中。粗糙度和N。L是紋理座標,貼圖的R通道存縮放(scale),G通道存偏移(bias)。(不使用B通道)

效果如下圖所示:

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

最棒的是,這張貼圖不依賴環境,在白光下是常量。所以你只需烘焙一次,就能把它當做資產用於你的shader。現在,我們必須合併從這些貼圖中獲取的數值,以得到鏡面反射光照。

下圖是粗糙度為0。1,只有間接鏡面反射的效果。

[譯] 面向美術師的基於物理的渲染(PBR)指南 _3

最後:

間接光照的虛擬碼如下所示:

//diffuse

indirectDiffuse = textureCube(IrradianceMap, refVec) * diffuseColor

//specular

lod = getMipLevelFromRoughness(roughness)

prefilteredColor = textureCube(PrefilteredEnvMap, refVec, lod)

envBRDF = texture2D(BRDFIntegrationMap,vec2(roughness, ndotv))。xy

indirectSpecular = prefilteredColor * (specularColor * envBRDF。x + envBRDF。y)

indirectLighting = indirectDiffuse + indirectSpecular

以上。資訊量挺大的,現在你應該要對基於物理的渲染要有個整體的瞭解了。下次,我們將深入研究,HAZ CODE!!

術語:

全域性光照(GI):

指場景中除直接光源的所有光照。

基於影象的光照(IBL):

使用影象作為光源的一種技術。

輻照度貼圖:

預計算的環境貼圖,其中包括環境的漫反射光照資訊。

球形諧波(SH):

請閱讀

重要取樣法:

近似積分結果的數學技術。

分解求和近似:

UE4的處理方法。將鏡面反射率積分轉換為兩個分解求和近似和,可輕鬆烘焙到預過濾(prefiltered)紋理中。

本文僅限於學習參考交流,請勿做商業用途和隨意轉載。

譯 Qinfei

2019/10/22