GPU加速DiffuseCubeMap經典計算(轉)

post0發表於2007-08-12
GPU加速DiffuseCubeMap經典計算(轉)[@more@]

  Diffuse Cube Map

  對於頂點x,我們知道由x反射向ω方向的光亮度

  Lo(ω)=∫brdf*Li(ω1)*vis(ω1)*max(0,dot(ω1,N))*dω1

  這裡brdf是x點的雙向反射分佈函式,Li(ω1)是由ω1方向照射到x的光亮度,vis(ω1)是x點朝ω1方向的可視情況, N是x頂點的法線。

  由於這個積分表示式比較複雜,精確的計算相當耗時,我們在使用的時候需要作相應的簡化。首先我們假設我們計算的所有表面都是存Diffuse的,這樣對於brdf我們可以簡單使用ρ/pi,於是上面的計算公式簡化成為

  Lo(ω)=(ρ/pi)*∫Li(ω1)*vis(ω1)*max(0,dot(ω1,N))*dω1

  接下來我們假設對於任意頂點x來說所有方向的vis都是一致的,也就是和方向無關,那麼我們又能把vis提出積分號

  Lo(ω)=(ρ/pi)* vis*∫Li(ω1)*max(0,dot(ω1,N))*dω1

  我們看到經過這樣簡化後的表示式對於每個不同的頂點來說只是和頂點的法線N相關了,於是我們可以預計算( ρ/pi)*∫Li(ω1)*max(0,dot(ω1,N))*dω1,儲存在一個Cube Map中,渲染的時候我們使用發現N來索引我們預計算的光照亮度值。最後使用這個光照亮度值乘上我們頂點儲存的vis就能得到我們最後的光照亮度值。

  GPU加速Diffuse Cube Map計算

  我們在使用CPU預計算(ρ/pi)*∫Li(ω1)*max(0,dot(ω1,N))*dω1的時候採用了蒙特卡羅積分法計算,具體的步驟是

  1 產生N個取樣光線,計算每個取樣光線和光照環境Cube Map的交點,得到每條光線的亮度值。

  2 對於每個我們需要計算的法線,我們計算出

  L(ω)=(ρ/pi)*((4*pi)/N)*∑(Li(ω1)*max(0,dot(ω1,N)))

  3 將我們計算出來到亮度值儲存在相應的法線所索引的Diffuse Cube Map的圖素。

  我們現在可以使用GPU來加速我們的計算

  1 首先還是一樣我們取樣N條光線,其次我們建立兩張FP16/32格式的Texture(能容納N個圖素),設定成我們的渲染物件(使用MRT).接著我們建立出N個point,每個point的法線就是所對應的光線的方向。我們將我們的光照環境Cube Map作為Texture設定好。我們渲染這N個point(保證每個point可以對應螢幕上的一個畫素)。在ps中我們使用法線來索引我們設定好的Texture,儲存在C0,將法線儲存在C1。這樣渲染完成後我們開始建立的兩張Texture,其中一張中的每個圖素對應著相應的取樣光線的亮度值Li(ω1),而另一張則儲存了向對應的取樣光線的方向ω1。

  2 對於每個我們需要計算出的法線方向(對應於Diffuse Cube Map的每個圖素),我們設定出一個point,它的位置對應於Diffuse Cube Map中的相應的Surface中的圖素的位置,法線就是我們需要計算的法線N(也就是從原點到設定的Diffuse Cube Map中的相應的圖素的位置).

  3 我們將上面第二步得到的每個point來求亮度值。我們建立一系列類似MipMap的FP16/32格式的Texture,其中最大的一張和我們第一步建立的Texture一樣的大小,首先將最大的一張設定成我們的渲染物件。我們設定好我們第一步得到的兩張貼圖,將我們的我們的point的法線設定到常量暫存器。在ps中,我們對於每個象素計算Li(ω1)*max(0,dot(ω1,N)),然後我們使用Down Sample的方法最終求出(ρ/pi)*((4*pi)/N)*∑(Li(ω1)*max(0,dot(ω1,N)))也就是對應於 1X1的Texture中的圖素。讀取出來儲存在對應的point的顏色屬性中。

  4 我們再得到了每個法線方向所對應的亮度值後,最後需要儲存在Diffuse Cube Map中,我們將我們第2步的所有的point分成6份,一份對應Diffuse Cube Map中的一個Surface。這樣我們只需要渲染我們的point的顏色到我們的Diffuse Cube Map的Surface中就完成了我們的計算。

  注 :在我們的計算中需要考慮HDR的因素

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951650/,如需轉載,請註明出處,否則將追究法律責任。

相關文章