Ray Tracking 蒙特卡羅積分和Path Tracking

上一節講到了渲染方程,可以獲得一個打出來的光線應該是自身發出的光和反射的光的總和。

Monte Carlo Integration(蒙特卡洛積分)

這是一種求解複雜函數(比如沒有解析式的時候)定積分的數值方法。
定積分就是求解概率密度函數面積的過程。

證明可以參考蒙特卡洛積分的無偏性:
https://zhuanlan.zhihu.com/p/365624460

這裏有一個重要的想法就是,不要想它是怎麼來的,只要證明它在期望上是無偏的,就可以使用它得到定積分了。
更直觀的,當分佈是均勻分佈的時候。可以認爲是取了N個採樣點,對採樣點\(x_i\)高度爲\(f(x_i)\),底是(b-a),面積就是\(f(x_i)*(b-a)\),N個求和:

注意:這裏的分佈也可以是其他分佈,但是要除以對應分佈。
綜上,蒙特卡洛積分:

因爲是數值的方法,用採樣去模擬積分的過程。所以採樣越多,誤差越小。

Path Tracking

在之前的Ray Tracking,主要是Whitted-Style的Ray Tracking),在Whitted-Style Ray Tracking中的定義是:
Whitted-style ray tracing:

  • Always perform specular reflections / refractions(執行的都是鏡面反光,對glossy這種反光沒有定義)
  • Stop bouncing at diffuse surfaces(遇到漫反射物體後會停下來,但是這是不對的,因爲漫反射出來的肯定也要渲染出來)

從這兩個角度上看,Whitted-Style Ray Tracing is Wrong(翻了之前的筆記,當初好像沒有具體講Whitted-Style Ray Tracing是怎麼做的,大概介紹了Whitted-Style Ray Tracing的含義是光線會多次彈射)。但是上一節從物理層面推出的渲染方程是正確的,但是問題就是怎麼解這個方程?

渲染方程的求解

求解包含兩個問題

  • 在半球上的積分
  • 遞歸

首先,關於反射方程中的積分,使用第一部分介紹的蒙特卡洛積分解決。這裏我們先簡單的在半球面上實現遵從均分分佈的採樣:\(p(w_i)=1/2\pi\),並且認爲打到的目標是光源。

我們定義shader(p,wo),p是彈射的位置,wo是彈射點到眼睛的連線。

帶入,可得:

進一步,當我們打到的東西是物體的時候,這也是一個相似的過程。物體收到別的光源和物體彈射的光,讓這個物體也變成一個光源(這裏的光源都是面光源),這個時候這個p就是眼睛,那麼這一物體光源q發出的光線就是shader(q,-wi)。wi是p到q的連線,對q來說,應該是-wi:

這裏理論上渲染方程已經表達出來了,但是真的這麼求解的話,會有一些問題:

  • 問題一:假如我們採樣很多,那我們的光線打出去之後,會以指數級增長。
  • 問題二:遞歸算法需要定義出口。【目前只有一個出口就是碰到光源,但是有一些終點沒打到光源的怎麼辦?】

針對問題一:
我們一次path tracking只進行一條線(也就是一個採樣),但是可以進行多次path tracking【我認爲也可進行多次採樣,只不過要自己決定策略,不然光線數量就會爆炸】。


針對問題二:
最簡單的想法是在一定彈射次數後跳出。但是這樣的話,因爲彈射次數越多其實我們的結果應該越好,但是不能無限的彈射下去,我們又想讓我們的結果接近應有結果。於是,使用了俄羅斯輪盤賭,【也是一個無偏估計】(這裏怎麼和彈射次數關聯起來呢?)
我們以P的概率射出,這部分得到的結果/P爲最終結果。(1-P)的概率不射出,這樣得到的結果是0。

在這之後,發現效率比較低。是因爲有大量的光線彈射出去沒有找到光源,得到0的返回值,這種光線就被浪費了。

那麼如果可以對光源進行採樣,是不是就會解決這種情況?但是蒙特卡洛積分只對我採樣的東西積分(也就是積分的東西肯定和積分域是對應的),因此做一個積分域的轉換在新的光源積分域上進行積分:

那麼,就要找到半球上的w立體角和光源的單位面積之間的關係。這裏應該是把光源想象成在一個更大的球上,成爲單位立體角的話要除以大R的平方:

最終,式子爲:

這樣的話,對半球的積分就變成了對光源的積分,這樣就是說打出去的光都會到光源上,那麼就是光源直接打到p位置上的部分,也就是直接光照。但是和之前不一樣的是,這部分不進行輪盤賭,我理解是這部分通過對光源計算可以準確算出來,就不要輪盤賭了。而間接的光【目的不是光源的物體,那這裏本身會發光又會反射的怎麼辦?】要進行輪盤賭來做一個無偏估計。

還需要判斷點和光源之間有沒有物體遮擋:

最終是振奮人心的渲染效果:

總結

到這裏,Path Tracking的基本想法就結束,當然存在一些問題。但是這裏僅僅關注最終的Path Tracking部分:

也就是一條path渲染一個眼睛看到的一個點,
shade(p,wo):

  • 直接光照計算的是能看到這個點的面光源【這裏如果有多個面光源應該要每個單獨計算然後加起來】:
    \(L\_dir=L\_i*f\_r*cos\theta *cos\theta'/ |x'- p|^2 / pdf\_light\) 【渲染方程+蒙特卡洛】

  • 當彈射目標不是光源的時候,使用俄羅斯輪盤賭(RR),計算\(L\_indir\):
    當生成的隨機數大於P_RR時,go die,返回0;
    小於P時,隨機採樣射線並且目標不是光源,然後計算:
    \(L\_indir=shade(q,-wi)*f\_r*cos\theta / pdf\_hemi/ P\_RR\)【蒙特卡洛積分除一次半球的面積,俄羅斯輪盤除一次P_RR】

return L_dir+L_indir

最終對來源於多個path的shade累加平均或者做別的操作,最終再轉化爲像素

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章