2020年6月8日 星期一

Dual Paraboloid Environment Mapping

  • 前言
在計算環境反射時,最常使用的就是 Cubemap。















圖片來源: Unity Manual

Cubemap 是由六張圖片對應六個方向所組成,

這對於 mobile 來說負擔太大,很容易造成效能瓶頸。

因此,本篇介紹一個較輕量的作法來實現環境反射,

此方法叫 Dual Paraboloid Environment Mapping。

  • 原理
先來看一個二元的數學方程式


這時透過觀察可以發現:當 x^2 + y^2 ≤ 1, 則 0 ≤ f(x,y)。

在上述的條件下,取 F(x,y) 上的任一點 P,

P 的座標可以記為 (x, y, f(x,y))。

在 P 點上,分別對 x 軸和 y 軸作微分,可以得到 P 點上的兩個切線向量。


接著,對 Tx 和 Ty 做外積,可以得到 P 點上的法向量 N = (x,y,1)。

這時取一條從原點到 P 點的向量 P',

計算 P' 相對於 N 的反射向量 R 。

的計算可以透過反射公式求得。


其中,上述所有向量都必須為單位向量。

因此,首先正規化向量 P' 和 N


得到兩個正規化向量後,帶入反射公式,求得反射向量 R


可以得知,反射向量為一個固定值(0,0,1)。


從上述的證明可以得到兩個重點
  1. 平面  f(x,y) 上任何一點的法向量 = (x,y,1),因為其 Z 軸為一個常數值,所以 N 可以視為一個二維變數。
  2. 從原點開始的任何一個向量 P',和平面 f(x,y) 接觸後的反射向量為一個固定值(0,0,1)。
這代表著我可以將一個三維向量 P' 在 Cubemap 取得的顏色資料 D

透過計算向量 P' 和平面  f(x,y) 交接處的法向量 N,

將顏色資料 D 儲存在一個2維陣列內。

而法向量 N 的計算就透過 P' 和固定反射向量 R 來求得。


但回頭看看平面方程式,為了方便說明我只顯示 X-Z 平面的形狀


這個平面只包含了上半部(+Z),

勢必要提供一個下半部(-Z)的二元方程式,才能完整獲得 Cubemap 所有範圍資料。


















圖片來源 : ScienceDirect - Environment Mapping

由於上半部和下半部個只需要一個2維陣列(i.e.一張2維貼圖)儲存 Cubemap 資料,

因此透過此方法,可以將一個 6張2維貼圖的資料,只用 2張2維貼圖儲存,

大大的減少資源需求。


  • Unity 實作

在實作範例中,我示範如何將一個使用 Cubemap 的 skybox,轉化成兩張 2維貼圖。

Dual Paraboloid map 一般用在即時的環境映射(事實上,我參考的文獻也是此種做法),

但一般 mobile 很少做這種計算,且兩者做法類似,

因此我在這裡示範 off-line 的 cubemap 轉換,若對 real-time 的環境映射有興趣,

可以參考我在文章最後列出的參考項目。


首先,在 Scene 裡面產生一個 Sphere 模型,
然後把攝影機設定在 Sphere 的原點為0,並設定 Clear Flags 為 Solid Color,顏色指定黑色
(在範例中,我是將畫面分成 +Z 和 -Z 兩個方向,所以攝影機的旋轉值全部設為 0)



接著,將 Sphere 掛上下面 Shader,並指定要轉換的 Cubemap


畫面變成


將輸出的畫面儲存。

接著把攝影機繞 Y 軸轉 180度,重複上述步驟,會得到下面結果




如此就完成了 Dual Paraboloid Environment mapping。

最後在附上 Dual Paraboloid Environment mapping 的 skybox shader。


  • 結論
本章節只討論 Dual Paraboloid Environment mapping 的其中一個應用,

就如同文章一開始所提到的, 一般常見的用法是用在 real-time 環境反射。

但兩者基本上做法是一樣,有興趣的人可以參考後面的參考連結,

修改上面提供的 shader 試試。


  • References



沒有留言:

張貼留言