1. 程式人生 > >PBRT學習筆記:光線跟蹤中的景深演算法

PBRT學習筆記:光線跟蹤中的景深演算法

景深是人眼視覺系統中的一種自然現象。同樣,相機裡面也有景深的效果,這是由於相機的成像光圈的半徑是有一定大小的,從而導致了成相平面中的某些點可以‘看到’鏡頭外面的一部分場景,而這些場景的共同作用,導致了一種模糊現象。
景深的效果在計算機圖形學中被應用廣泛,電影,遊戲裡面經常會利用景深特效來強調畫面重點。相應的,已經有了很多成熟的演算法在不同的渲染方法上,光柵化可以很高效的實現景深的演算法。而本文將簡單介紹景深效果在光線跟蹤中的實現,以及一些基本原理。
首先,看看景深效果是什麼樣子,讓我們對他有個直觀的印象:

dof_newno_dof

這個是經常被用來做試驗的toasters場景,場景中,中間的toaster沒有被模糊,而其餘的toaster根據與視點的距離有著不同程度的模糊。下面我們將簡單的介紹一下這種演算法是如何實現的。

image
如果成像平面上有一點p0,p0可以向光圈發射無數條光線(因為光圈是有大小的,它不是一個理想的點),而這些光線透過光圈後,會在焦距平面相交(這個過程可以通過一些運算推匯出來)。如果場景中剛好有一個物體在這裡擋住了視線,這個p0所能看到的就是一個清晰的點,而這種情況的概率很小,所以這些光線更可能是在其他東西相交。而似乎從這個理論上來說,所有物體都應該被模糊了,只是程度不同。反過來思考,上圖中,p1和p2兩點透過光圈在成相平面上投影了不同的形狀,其中p2的投影剛好是一個點,而p1由於距離焦距比較遠,從而在成像平面上影射出了一塊區域。由於計算機是利用有限資源來進行計算,所以實際上我們在螢幕上看到的圖片是由一個一個畫素所組成的。如果上述p1’所成像的區域小於一個畫素的區域,從而它就不會被模糊,或者說它雖然被模糊了,但是由於計算機中的圖片表現形式,這種模糊是無法表現出來的,所以可以認為是沒有模糊的。那麼焦距實際就不是一個平面了,而是距離平面一定範圍的一段空間,在這個空間裡面的物體會被清晰的呈現,而外面的物體則會不同程度的模糊。物體模糊的程度是有物體與focal plane的距離和光圈大小共同決定的。
上面簡單描述了一下景深形成的基本原理,下面將介紹一下這個演算法如何應用到光線跟蹤演算法中。

image

上述模型中,我們拋開從成像平面到鏡頭的光線投射過程。在一個沒有景深效果的ray tracer裡面,光圈的形狀被定義為了一個點,即大小為0。所有一級光線都是從光圈所在點,即視點,出發的。為了模擬景深效果,我們首先要賦予光圈一定的大小。當光圈有了一定的面積後,我們可以在光圈上隨機的取一點,而並不一定是光圈的中心(沒有DOF效果的ray tracer的視點)。本文中的取樣是在光圈上完全隨機的取樣,貌似PBRT採用了更復雜的演算法進行取樣。
一級光線的original point是可以按照上述辦法搞定的,但是問題在於光線的方向是如何計算的。理論上來講,可以按照光線以及一些鏡頭引數根據snell定律計算,但是這個過程複雜而且運算效率很低,所以一般都是通過其他辦法來避免。事實上,通過光圈任何一點,折射出的一級光線都是在focal plane處相交的。我們已經確定了一級光線的原點,只要在找到光線上的一點,我們就可以確定光線的方向。所以我們只需要找到任何一個光線與focal plane的交點,即可以確定該光線的方向。為了簡化,這裡我們利用經過光圈中心的光線來找到與focal plane的交點,因為這個光線是不需要進行折射計算的,相對來說簡單很多。
在光線跟蹤演算法中,只需要改變一級光線就可以生成景深效果了,所以景深效果在PBRT中的實現是放在Camera的類中的,它作為projective camera的一個基本功能存在,和其他計算模組關係相對較遠。當然我們需要為每個象素多采樣,才能夠達到更好的效果。

low_sample_dofdof_new

左圖是每個點取樣一次,自然會有一些噪音。而右邊的圖片,每個象素取樣了128次,基本上可以滿足視覺要求。
本文簡單介紹了一下景深效果的基本原理以及光線跟蹤中的模擬方法,但是這種方法雖然可以生成帶有景深效果的圖片,效率卻隨著取樣率有著嚴格的線形的下降。