1. 程式人生 > >OGL(教程24)——陰影對映2

OGL(教程24)——陰影對映2

原文地址:http://ogldev.atspace.co.uk/www/tutorial24/tutorial24.html

背景知識:
原文地址:http://ogldev.atspace.co.uk/www/tutorial24/tutorial24.html

背景知識:
前一小結學習陰影對映背後的基本原理。也學習瞭如何把深度緩衝渲染到一張紋理,然後緊接著從深度緩衝取樣並繪製到螢幕。本節我們將學習如何使用陰影對映圖繪製影子。

我們知道陰影對映是一個雙通道技術。第一次渲染是從燈光位置渲場景,讓我們回憶下第一次渲染時,位置向量z分量發生了什麼。

  1. 傳入到頂點著色器中的頂點資料是定義在本地空間的。
  2. 頂點著色器把頂本地空間的位置,轉換到裁剪空間,然後傳入到管線。
  3. 光柵化器執行透視除法(位置向量除以w分量)。這個把位置向量從裁剪空間轉換到NDC空間。NDC空間下的座標xyz分量對映到[-1,1]範圍。超出這個範圍的被裁剪掉。
  4. 光柵化器把xy座標對映幀緩衝的維度(比如800600,或者是1024768)。這個座標是螢幕空間座標。
  5. 光柵化器接收三角形三個頂點的螢幕座標,然後進行插值。對每個畫素建立一個唯一的座標。z值依然是[-1,1]區間,它也被插值,所有每個畫素有自己的深度。
  6. 由於第一個通道我們關閉了顏色寫入。深度測試依然執行。為了比較當前畫素的z值,和之前深度緩衝中的z值。如果新的z值小於取出的深度值,那麼深度值被更新。
    這上面的處理過程中,我們從光源的視角計算深度值,並存儲起來。第二次渲染,我們從攝像機的角度渲染,得到另外一個深度。但是我們需要兩個深度——一個是用於正確把三角形顯示在螢幕上,另外一個是檢測畫素是否在陰影內。使用的技巧是,在陰影對映時候維護兩個位置向量,連個wvp矩陣。一個wvp矩陣是從光源位置,另外一個是從攝像機位置。頂點著色器接收的是頂點本地位置,但是輸出兩個向量:
  7. gl_Position,是使用攝像機WVP矩陣變換得到的位置
    2.一個平的向量,是通過光源位置的WVP矩陣變換得到。
    第一個向量會傳入上面的處理過程(得到NDC空間),這個會被正常的光柵化過程使用。第二個向量,會被光柵器插值,每個畫素著色器呼叫會提供自己的值。所以現在,對於每個物體畫素,我們同樣有了從光源出看到的裁剪座標。很有可能這從兩個視角看到的物理畫素是不同的,但是在三角形中的位置是相同的。所有剩下的就是根據裁剪座標從陰影對映深度圖中取出深度。取出之後,我們比較當前點的深度和取出的深度值,如果取出的深度值小於當前的深度,那麼說明此點在陰影內。

那麼如何在片段著色器中使用裁剪空間座標取出深度值呢?我們分為兩個步驟:

  1. 因為片段著色器接收的是裁剪空間座標,光柵器沒有執行透視除法。但是這個可以手動做下,就是每個分量處於w分量,就得到了NDC空間。
  2. 我們知道NDC空間的xy都在-1到1之間。在上面的第4步驟,光柵器把NDC空間對映到螢幕空間,然後使用它們儲存深度。我們將要取樣深度,所以我們需要貼圖的座標在[0,1]區間。如果把[-1,1]對映到[0,1],我們將會得到和紋理座標,這個和陰影貼圖有相同的位置。比如x在NDC中為0,貼圖的寬度為800。0在NDC中需要對映到貼圖的座標為0.5(因為他是-1和1的中點)。所以紋理座標為0.5的對映到400.
  3. 把x和y對映到NDC空間,如下:
u = 0.5 * X + 0.5
v = 0.5 * Y + 0.5