天天看點

Lightmass分析(四) 光子追蹤Intro發射直接光子發射間接光子标記 IrradiancePhoton将 IrradiancePhoton 緩存到對應的 TextureMapping 中計算 IrradiancePhoton 的 Irradiance緩存物體表面各處的光照結果參考文獻

Intro

Lightmass分析 系列文章前言及目錄

Lightmass 借用 Photon Mapping 算法生成儲存全局光照資訊的光照貼圖. 本文将着重介紹 Lightmass 的光子追蹤部分.

光子追蹤的主要工作是: 發射直接光子, 發射間接光子, 緩存物體表面各處的光照結果. 在 Lightmass 中計算光子的 Irradiance 之前還會對光子進行标記和緩存操作. 這些預先的操作目的是根據空間關系先對光子進行一次篩選, 減少無用的光子計算, 提高運作效率, 并為後面的流程做資料準備.

發射直接光子

直接光子的生成過程比較簡單. 從光源發射一定數量的光線并與場景求交, 所得的交點就是直接光子的位置并可以根據場景光源計算出光子所對應的 power.

另外在得到直接光子之後, Lightmass 還會根據光子所在表面的 BRDF 屬性産生一組被稱為 IndirectPath 的射線, 這組射線會決定是否需要産生間接光子以及産生間接光子時采樣光線的方向.

Lightmass分析(四) 光子追蹤Intro發射直接光子發射間接光子标記 IrradiancePhoton将 IrradiancePhoton 緩存到對應的 TextureMapping 中計算 IrradiancePhoton 的 Irradiance緩存物體表面各處的光照結果參考文獻

發射間接光子

間接光子的生成過程與直接光子的類似, 隻不過間接光子會開始考慮光子接觸表面後的反彈等行為. 需要注意的是為了更好的間接光照效果, 間接光子并沒有在上一步産生的直接光子基礎上繼續生成. 而是以更大的密度重新産生了一遍直接光子, 并在此基礎上生成間接光子. 另外因為第一次反彈和後續反彈在計算輻照度時的貢獻權重不同, 這裡會将間接光子分成兩個光子圖分别儲存.

Lightmass分析(四) 光子追蹤Intro發射直接光子發射間接光子标記 IrradiancePhoton将 IrradiancePhoton 緩存到對應的 TextureMapping 中計算 IrradiancePhoton 的 Irradiance緩存物體表面各處的光照結果參考文獻

标記 IrradiancePhoton

這裡标記的是 IrradiancePhoton 是否存在存在直接光照的貢獻, 這可以通過判斷目前光子一定範圍内是否存在Direct Photon來确定 (這也展現出我們将光子圖一分為三的意義). 這個名額會影響目前 IrradiancePhoton 的搜尋範圍, 存在直接光照貢獻的 IrradiancePhoton 搜尋範圍會更小, 也就是在空間中某點處查找其周圍的光子時更不容易被找到. 或者說有直接光照貢獻的 IrradiancePhoton 影響範圍要小一些.

将 IrradiancePhoton 緩存到對應的 TextureMapping 中

這裡我們需要周遊 TextureMapping 中記錄的物體表面上的每一個點, 為此我們需要對其進行光栅化操作. 擷取到目前頂點之後查找其一定範圍内與其距離最近的 IrradiancePhoton, 如果存在則将此光子記錄在 TextureMapping->CachedIrradiancePhotons 中并将此光子标記為已使用. 在後面計算光子的輻照度時, 如果光子沒有被标記為已使用, 則直接跳過計算. 這其中的邏輯在于: 沒有被标記為已使用的光子意味着在空間上他沒有影響任何一個表面, 是以不需要計算.

另外需要注意的是我們周遊每一個位置查詢與其距離最近的光子, 由于光子本身是離散的, 這就形成了一定範圍内的模型表面都受到同一個光子的影響.

計算 IrradiancePhoton 的 Irradiance

這裡我們會周遊之前所有的 IrradiancePhotons, 跳過未使用的光子, 然後計算光子的 Irradiance. 光子的 Irradiance 涉及直接光照貢獻, 第一次反彈貢獻和第二次及後續反彈貢獻三部分.

其中直接光照部分在預設設定下在這裡不起作用. Lightmass 通過 CalculatePhotonIrradiance 方法計算光子的 Irradiance. 他首先尋找目标光子一定範圍内的所有光子, 然後對這些光子使用 ConeFilter 計算出目前光子的 Irradiance 并更新目前光子.

需要注意的是我們上一步緩存的是 IrradiancePhoton 的指針, 這裡的修改也就自動同步到了 TextureMapping->CachedIrradiancePhotons 中.

Lightmass分析(四) 光子追蹤Intro發射直接光子發射間接光子标記 IrradiancePhoton将 IrradiancePhoton 緩存到對應的 TextureMapping 中計算 IrradiancePhoton 的 Irradiance緩存物體表面各處的光照結果參考文獻

PS: 從圖中可以看出現在緩存的光照明顯呈現色塊效果

緩存物體表面各處的光照結果

我們之前已經緩存了模型表面受到的間接光照值, 接下來我們再将直接光照的結果也應用到緩存中就可以得到完整的光照緩存.

為此我們需要先周遊物體表面上的每一個點(和之前一樣通過光栅化來實作這個空間上的周遊). 這時我們之前緩存的 CachedIrradiancePhotons 開始發揮作用. 由于 CachedIrradiancePhotons 和光栅化之後的 TexelToVertexMap 是一一對應的, 那麼我們在周遊 TexelToVertexMap 時就可以直接通過下标判斷對應空間位置上是否存在光子并擷取光子的 Irradiance.

這一步會将光子的 Irradiance 資料, 直接光照陰影資訊和模型表面材質整合到一起并儲存到 TextureMapping->SurfaceCacheLighting 中. 不過這時的光子還沒有對其周圍的環境産生影響, 光子對環境的作用還需要通過最後的 Final Gather 确定.

Lightmass分析(四) 光子追蹤Intro發射直接光子發射間接光子标記 IrradiancePhoton将 IrradiancePhoton 緩存到對應的 TextureMapping 中計算 IrradiancePhoton 的 Irradiance緩存物體表面各處的光照結果參考文獻

參考文獻

Jiff:Lightmass分析之 經典Photon Mapping算法介紹

Jiff:LightMass源碼分析之光子追蹤實作

Jiff:LightMass源碼分析之光照評估