- 前言
在上一篇,我將 rendering equatiom 分成了 Diffuse 和 Specular 兩個部分,
並 pre-compute(預先計算) Diffuse 部分,將結果儲存在一個 cubemap 內。
本篇會承續上一篇未處理的 Specular 部分,討論如何實作 pre-compute,
以減少 real-time 渲染的負擔。
首先將 Specular 的部分使用在 淺談 physically based rendering (4)
以減少 real-time 渲染的負擔。
- Specular BRDF
首先將 Specular 的部分使用在 淺談 physically based rendering (4)
提到的 Cook-Torrance Model 展開,
其中:
ks 是物體的反射率(註1)。
在這裡,可以觀察到反射的結果會受到兩個變數的影響,
ωi (入射光方向) 和 ωo (觀察者方向)。
對這兩種的所有組合做積分是不實際的。
因此,勢必要想辦法減少變數的數量,才能達到實用的階段。
- split sum approximation
首先,使用 Monte Carlo method (蒙地卡羅積分法) 對 Specular BRDF 做積分,

其中
p : 是 probability density function (簡稱 pdf)
lk : 使用 importance sampling (重點採樣) 計算出來的反射光方向樣本。
根據 [2]、[3] 得知,

其中
p : 是 probability density function (簡稱 pdf)
lk : 使用 importance sampling (重點採樣) 計算出來的反射光方向樣本。
根據 [2]、[3] 得知,

將 pdf 代入積分式,得到

如此,原來的積分式就被分成了兩個部分
前面的部分為 Integral of BRDF (簡稱 DFG 項),
後面的部分為 Integral of Lighting (簡稱 LD 項)。
這種將積分式拆開後分別處理,
最後再將結果一起計算的方法稱之為 split sum approximation [2]。
觀察 DFG 項,可以發現變數的數量還是很多,
因此需將算式整理,看看是否能把變數數量壓到最小。
首先為了簡化算式,根據 淺談 physically based rendering (4) 提到的效能優化技巧,
將 G 項和分母結合使其成為 V 項。

接下來展開 F 項,
在 淺談 physically based rendering (4) 我是使用 Fresnel-Schlick approximation 實作F項。

將 F 項代入積分式,可以得到

這種將積分式拆開後分別處理,
最後再將結果一起計算的方法稱之為 split sum approximation [2]。
- Integral of BRDF
觀察 DFG 項,可以發現變數的數量還是很多,
因此需將算式整理,看看是否能把變數數量壓到最小。
首先為了簡化算式,根據 淺談 physically based rendering (4) 提到的效能優化技巧,
將 G 項和分母結合使其成為 V 項。

接下來展開 F 項,
在 淺談 physically based rendering (4) 我是使用 Fresnel-Schlick approximation 實作F項。

將 F 項代入積分式,可以得到

由於同一個渲染物體 F0 是相同的,所以可視為一個常數。
到了這裡,已經將變數數量限制到一個可接受的範圍內,
half-vector 和 light-vector 可以用 importance sample 計算出來,
因此變數只剩下 roughness 和 view-vector 而已。
為了方便將 pre-compute 結果作為一個 lookup table 儲存在一張 texture 上,
需要將變數範圍限制在 [0,1] 之間,
所以,在 pre-compute 時,將 roughness 和 NdotV (normal 和 view-vector 的內積)作為引數,
計算出 DFG1 term 和 DFG2 term 的積分結果,儲存在 R和G通道。
在 run-time 時,將物體的 F0、roughness 和 NdotV 資訊引入來計算出結果。
在 pre-compute 實作上,我是使用 Unity 的 Compute Shader 來處理,
代碼如下
函數 ImportanceSampleGGX 和 Hammersley
可以參考 importance sampling (重點採樣)、Low-discrepancy sequence (準亂數列)
這兩篇文章的討論。
比較值得注意的是在 淺談 physically based rendering (4) , G 項的 K值我是使用

但在 IBL 的 pre-compute , K 值我是使用 k = α / 2。
主要原因是參考了 [2] 的說明,認為 k = α / 2 在 IBL的計算上可以得到一個比較好的結果。
執行後,會得到下面的一個圖片(註1)

U軸為 NdotV, V軸為 roughness
- Integral of Lighting
接下來觀察 LD 項,可以發現和在 Image Based Lighting (1) 裡,
做 Diffuse 的 pre-compute 很類似,都是收集周遭環境光源做積分運算。
但不同的是,為了簡化 Specular BRDF 積分式的變數數量,
使用 importance sampling 去找出取樣點,分割成 LD 項和 DFG 項。
因此,不能像處理 Diffuse 一樣,
對 Spherical Coordinates (球面座標系) 的 θ 和 φ 做等間隔取樣,
必須用 importance sampling 回傳的取樣點,去做積分計算。
但這裡發現了一個問題,在 LD 項只有 importance sampling 回傳的取樣點法線向量,
光靠法線向量是無法得到周遭環境光源的光線資訊(註2)。
為了解決這個問題,令 normal = view = reflect [2],
讓 importance sampling 回傳的取樣點法線向量,可以直接取得光線資訊。

圖片來源 : Learn OpenGL - Specular IBL
根據上圖可以觀察到,如果假設 normal = view = reflect 時,
反射結果會變得模糊但仍然可以保持原始輪廓。
[2] 為了減少假設帶來的失真,發現可以在 LD term 算式內,
加入 NdotL (normal dot light-vector) 作為權重值,來近似原始效果。
在 pre-compute 實作上,我同樣是使用 Unity 的 Compute Shader 來處理,
代碼如下
其中,要注意的是 LD term 算式存在著 roughness 這個變數,
根據 [5] 的文章,可以將 roughness 分成數個階段,
將每個階段的結果存儲在 cubemap 的 mipmap 裡面。
在實作上,我是分成5個階段 (i.e. roughness = 0, 0.25, 0.5, 0.75, 1),
由於 roughness 越高,光線越模糊,
因此根據 roughness 的程度由小到大依序儲存在 cubmap 的 minmap 裡。
根據 [5] 的文章,可以將 roughness 分成數個階段,
將每個階段的結果存儲在 cubemap 的 mipmap 裡面。
在實作上,我是分成5個階段 (i.e. roughness = 0, 0.25, 0.5, 0.75, 1),
由於 roughness 越高,光線越模糊,
因此根據 roughness 的程度由小到大依序儲存在 cubmap 的 minmap 裡。
- 結論
到了這裡,已經完全說明了 IBL 的基本原理,
在下一篇會展示渲染結果並和 Unity 內建的 standard shader 做個比較和分析。
- References
3. "Physically Based Shading at Pixar" SIGGRAPH 2013
4. Siggraph 2014 : Moving Frostbite to Physically based rendering V3
5. GPU Gems 3 - Based Importance Sampling
4. Siggraph 2014 : Moving Frostbite to Physically based rendering V3
5. GPU Gems 3 - Based Importance Sampling
- 附註
1.在 [2] 文章裡面,是使用 R16G16 的圖片格式來儲存 Integral of BRDF 的資料,
主要是認為精準度會對渲染結果有很大的影響。
但在我的實作中,因為考慮到 mobile 裝置支援性,選擇了傳統的 RGB24格式,
這部分可以視情況做修改。
2.本篇是延續 Image Based Lighting (1) 使用 Environment Map (環境貼圖),
作為周遭的環境光源,因此需要反射光向量來取得光線資訊。
主要是認為精準度會對渲染結果有很大的影響。
但在我的實作中,因為考慮到 mobile 裝置支援性,選擇了傳統的 RGB24格式,
這部分可以視情況做修改。
2.本篇是延續 Image Based Lighting (1) 使用 Environment Map (環境貼圖),
作為周遭的環境光源,因此需要反射光向量來取得光線資訊。
沒有留言:
張貼留言