PRT相關 學習筆記(零基礎)

PRT相關 學習筆記(零基礎)

引子

想要入門計算機渲染,於是讀了一些PRT相關的知識,雖理解並沒有深入全面,但同樣受益匪淺。接下來想先去了解一下BRDF,希望藉此可以對渲染方面了解更全面一些。

由於PRT學習暫時會告一段落,所以先把現在了解到的知識記錄下來,留給以後的自己閱讀,也希望對同樣想要了解PRT的人有一定幫助。

參考資料:

www0.cs.ucl.ac.uk/staff

參考資料是2005年發表的,所以接下來的部分觀點也是以2005年的技術為背景的。

基本介紹

Precomputed Radiance Transfer 是什麼?

物體在不同的光照下的表現不同,PRT是一個計算物體在不同光照下的表現的方法。光線在一個環境中,會經歷反射,折射,散射,甚至會物體的內部進行散射。

為了模擬一個相對真實的表現,可能需要考慮來自所有方向的光線,所有可能的傳播形式。我們可以通過一種預計算的方式,使最後的渲染可以以實時的效率呈現出來。

預計算便代表著有什麼東西是不變的,如果在計算過程中任何對象都是時刻發生變化的,那麼預計算本身便不可能。

所以PRT方法確實存在一些限制:

1. 不能計算隨機動態場景的全局光照

2. 場景中物體必須是靜態的

3. 物體與物體之間的交互暫時還無法處理(2005年)

一些背景知識

首先,渲染(Rendering)是什麼?著色(shading)又是什麼?

渲染是輸入幾何信息,材質信息,光照信息,生成一張圖片的過程(繪製到屏幕上的過程)。

而著色指的是計算某個點上有多少光線經過傳播到了觀察者的眼睛裡。

而如何計算,光學上是有一個完善的方程的。

Rendering Equation

渲染方程表示的內容是,受光線照射的一個點,沿特定方向觀察而表現出來的顏色。也就是說,不同的光照,不同觀察方向,和不同的材質,都會影響我們最後看到的顏色。

L(p
ightarrow ar{d})=L_e(p
ightarrow ar{d})+int f_r(p,ar{s} 
ightarrow ar{d})L(p leftarrow ar{s})H_{N_p}(-ar{s})ds

等式的左邊表示從點p沿d方向離開的光線的能量。

等式右邊的第一項 L_e 表示點p沿d方向發出的光線。

再之後是一個積分式子,先不看積分符號,積分式子內部表示的是從s方向到來的光線,最後沿d方向發射出去的能量。而積分是對s進行積分,也就是說,之後的那一項表示的是所有到達p點的光線,經過p點後,沿d方向發反射出去的能量。

我們現在再按順序解釋三項中的每一項。

f_r 是BRDF函數,代表的是物體的材質屬性,表示從s方向射來的光線,反射到期望方向的能量比,所以它的輸入有點p,有入射方向和出射方向。在漫反射中,我們可以把這一項簡化成一個常量,因為漫反射的時候沿各個方向反射的能量都是相同的。

L 函數表示沿s方向到來的光線的輻射的能量,這會是PRT比較著重關注的地方,因為光線的傳播是很難計算的,它可能經過很多的反射和折射,但是如果我們可以把一個點的一個小範圍內所有光線都計算清楚,在這個小範圍內的所有光線都能直接照射到那個點,那麼我們的計算效率就能提高很多。

H_{N_p} 表示一個p點法向量和向光源方向(光線的傳播的反方向)的兩個向量的cos值。

Neumann Expansion

可以看出光線在物體之間的反射幾乎是無窮盡的,而諾曼展開就是一個將光線傳播近的無限整理重現的方法。我們知道光線每次打到物體上,都會有一部分進入物體內部,也就是說光線的能量會下降,也就是說,反射次數太多的光線對最後結果影響不大。那麼,當有一個式子可以把光線經過不同反射的結果分離開來,我們再省略掉反射次數太多的部分,就可以得到可以計算的近似函數了。

我們先看諾曼展開的式子:

L(p
ightarrow ar{d})=L_0(p
ightarrow ar{d})+L_1(p
ightarrow ar{d})+...

L_0 代表光線到達p點前沒有經過碰撞,也就是說直射光。

L_1 表示經過了一次碰撞,以此類推,這個式子特別靠後的部分我們就可以將它忽略掉。

我們再來看看 L_0 是什麼:

L_0(p 
ightarrow ar{d})=int_ Omega f_r(p,ar{s} 
ightarrow ar{d})L_{env}(ar{s})V(p 
ightarrow ar{s})H_{N_p}(-ar{s})dar{s}

和渲染方程有著細微的差別,渲染方程中的L函數表示沿s方向到來的光線的能量,而這裡表示的只是沒有經過任何碰撞的沿s方向到來的能量,也就是說,就是環境光(注意下標:environment),那麼為什麼還多了個V函數呢?

我們並不知道環境光照射到來的時候,是否被什麼遮擋,如果被遮擋住了,這個方向的V函數就為0,反之則為1,V函數只是一個有兩個值的函數。

那麼 L_1 又是怎樣的呢?類比一下,其實只用把 L_{env}(ar{s})V(p
ightarrow ar{s}) 換成 L_0(p leftarrow ar{s})(1-V(p
ightarrow ar{s})) 即可:

L_n(p leftarrow ar{s})=int_{Omega}f_r(p,ar{s} 
ightarrow ar{d})L_{n-1}(p leftarrow ar{s})(1- V(p 
ightarrow ar{s}))H_{N_p}(- ar{s})ds

簡單來說,第N項表示的是經過先前所有碰撞後的能量有多少反射到目標方向。

Basis Function

把一個函數近似成多個基本函數的組合。這一個思想就像是用不同的空間坐標系表達空間中的點。把一個函數用不同基本函數表示,如果基本函數具有很好的物理意義,那麼係數就可以很好表示函數的性質。

一個例子: B_i(x) 代表基函數, c_i 代表對應基函數的係數。

這裡只提到Basis Function的基本思想,具體細節請詳見參考鏈接。接下來會進行PRT的具體的實現。

通用PRT方法

通用的目標是,在光線會發生變化,效果會隨視角不同而不同(也就是不是簡單的diffuse),場景中的物體可能會相對光源產生剛體變換(包含旋轉移動,不會變換形體)的情況下依舊可以適用。

除此之外,通用PRT也可以計算物體周圍的點的光照信息(或者說,物體周圍點的光照信息可以藉助物體的光照計算出來),那麼場景中存在移動物體的時候,我們就可以計算它的光照是如何受周圍物體影響,這樣再加上顏色混合和軟陰影就可以對移動物體進行shade。

對於一個給定的光照環境來說,輸入能量到輸出能量存在的關係是線性的。也就是說,對於一個固定的環境上的某個點,存在一個線性運算元將它的輸入能量轉換成特定方向的輸出能量。我們可以把這些線性運算元表示成一系列的線性基函數,如果表示輸入和輸出能量函數的基函數是一致的,我們是不是就只用記錄它們對應基函數的係數就好了?

基函數有很多種選取方法,這篇博客可能不會涉及到太細節的地方。

對於一個環境光(一個均勻的包裹場景的無限大的不受場景影響的光球)來說,其實並不能簡單的做線性計算,因為這其中還存在著一個問題:

假設我們在自由空間放置了一個非常小的物體(點P),只有在場景中的物體沒有替它擋住光線的方向,它才能接受到直射光線。所以我們需要對最開始的環境光進行裁剪。點P接收到的光線是什麼呢?這些光線可能從環境光直射,也可能經過了多次反射。從光線的角度思考有些困難,但是如果從所看到的景物來看,可能會很直觀。當你處在P點時,你所見到的環境的樣子,就是射向P的所有光線。為了能夠讓計算也如此「友好」的進行下去,我們定義一個量用來協助我們:

L_{xfer}(p leftarrow w) 到達P的所有光線(即P能看到的所有)

現在我們可以介紹一下PRT的大致流程了:

  1. 首先對於一些採樣點,我們預計算出在該點上 L_{env} 是通過怎樣的線性變化到 L_{xfer} 的,記錄線性變換用到的矩陣。
  2. 使用這些矩陣計算出特定點的 L_{xfer}
  3. L_{xfer}f_r 以及 H_{N_p} 乘積做積分,求出反射出的光線

Directional Inner Product

此處先引入一個數學標記,為了更好的進行接下來的說明:

int_{Omega(p)} a(p,w)b(w)dw=:<a(p),b>

a函數輸入是頂點和方向,而b函數只與方向有關。

Basic Idea

emmm……還記得前文提到的函數空間和基函數那一套嗎?我們要拿來用了。

我們要把 L_{xfer} 轉換到一個球面函數空間,或者說,把光照函數投影到球面上,再或者說,我們把球面離散化,得到一系列的基函數,然後用這些基函數模擬光照的函數,看怎麼好理解了。

L_{xfer}(p leftarrow w) approx sum_{i=1}^{m}{l_i^pZ_i(w)}

l 代表係數,而Z代表基函數。也就是說, l 是用一系列基函數表示p點周圍輻射的權重。

我們可以把右邊的式子看成是矩陣的乘法(函數乘係數):z(w)^T cdot l^p

有鑒於此,我們可以對 L_{env} 同樣處理: y(w)^T cdot l

其中,第一行的 l^p 決定了最後的光照,是我們所要求的量,而第二行的 l 是最初的環境光的係數,是我們已知的。我們需要做的便是找到這兩種係數之間存在的關係,這個關係是線性的,所以可以用矩陣表示,我們把關係用數學式子表示: l^p=T^pl

其中 T^p 被稱為p點的傳播矩陣,它將環境光近似映射到p點附近的光。

考慮矩陣運算,可以知道一些關於矩陣的性質。矩陣的第i列表示用來表示原始光照的第i個基函數如何影響最後的結果。

所以對於矩陣的第j行第i列,指的就是投影到 L_{xfer} 的第i個基函數的權重,我們可以反向表示出這個量來:T_{ji}^p=<L^i_{xfer}(p),	ilde{z_j}> = int_Omega L^i_{xfer}(p leftarrow w)	ilde{z_j}(w)dw

簡單情況

只有直射光線,只接受物體本身的陰影,不考慮到達p點之前光線經過了其他碰撞。簡單情況況可以幫我們抽象的理解計算過程。

到達p點的直射光線可以被表示為最初的環境光照和可見性函數的乘積:

L_0(p leftarrow w)=L_{env}(w)V(p,w)

那麼第i個基函數所對應的光線能量就是:

L_0^i(p leftarrow w)=y_i(w)V(p,w)

V是一個二元函數(正如我們前面提到的那樣),如果有物體在w方向擋住了光線,那麼V(p,w)就為0,否則為1。

因此 T_{0,ji}^p=int_Omega y_i(w)	ilde{z_j}(w)V(p,w)dw

那麼,我們可以表示出最後的光照結果:

L(p leftarrow w) approx sum_{j=1}^ml_j^pz_j(w)=sum_{j=1}^{m}z_j(w)[sum_{i=1}^nl_iT_{ji}^p]=z(w)^TT^pl

推薦閱讀:

VIVUE大咖訪談丨李楊:好作品需要導演善於講故事
正在學習建模渲染,望各位大神指明方向?
substance到影視渲染流程介紹
為什麼我看壞arnold渲染器的發展

TAG:渲染 | 計算機圖形學 |