聶宇
(四川大學計算機學院,成都610065)
以巨大的計算量為代價,全局光照(間接光照)技術能大幅度提升渲染圖像的真實性。其計算復雜度存在于多個方面。首先,全局光照解決方案需要判斷3維場景中任意兩點的可見性。在基于光柵化管線中快速進行可見性判斷則更加困難。其次,全局光照的計算要求對每個著色點的法半球所有入射光線進行積分。即使在圖形硬件快速發展的今天,全局光照應用的實時性也很難得到保障。高DPI 屏幕、立體渲染、VR 設備的高幀率要求更是加劇了真實性與效率的矛盾。因此,現今大部分應用都不支持精細的全局光照(局部的、動態光源和動態場景),如圖1 所示,而是主要通過預計算的輻射傳輸[2]來進行靜態預計算或有限形式的動態光照。
在交互式渲染的前提下,就如何生成令人信服的全局光照效果近年來涌現了大量的解決方案。光場探針技術便是其中運用較為廣泛的一類方法。探針的表現形式各有不同,例如JT Hooker 等人利用立方體貼圖編碼光場[3],而Thomas 等人則利用八面體貼圖進行光場編碼[4]。傳統光場探針技術的局限性在于它們預計算的特性和它們對場景光場進行采樣的方式。由于生成探針數據的預計算十分耗時,因此,傳統光場探針僅能處理靜態光源和靜態場景的情形。此外,對輻射照度進行空間插值和預濾波的高光采樣策略極可能造成鋸齒和漏光現象,如圖2 所示。

圖1 精美的全局光照效果
隨著圖形硬件的飛速發展,實時光線追蹤成為熱門研究領域。DDGI(Dynamic Diffuse Global Illumination)作為首先利用硬件光線追蹤的渲染算法,拓展了McGuire 等人[5]提出的傳統基于探針的全局光照,彌補了原先只支持靜態場景的劣勢,使得DDGI 可以被廣泛使用。
然而,DDGI 也并非毫無缺點。即使現在已經有硬件光線追蹤的支持,在場景比較復雜的情況下,DDGI在每一個探針處仍不能發射大量光線。同時,DDGI 將多次反射的計算代價,分攤到若干幀,并通過混合的方式更新每個探針的輻照度。因此,DDGI 主要存在2 個問題:首先,首先是通過混合的方式分攤計算代價會導致閃爍的問題;其次,是由于混合,當場景存在劇烈變化時,會觀察到GI 效果有從一個地方“流動”到另一個地方的問題。
我們注意到,造成這些問題的根本原因在于從探針處發射的采樣光線數目較少。當場景簡單時,我們可以通過增加采樣光線數目來避免這些問題。但當場景復雜程度升高,場景中布滿的探針數目隨之增加,在每個探針多發射采樣光線已經無法實時。因此,本文提出可以通過重要性采樣,使得即使每個探針只發射少量光線也可以獲得比較好的效果。

圖2 左圖漏光,右圖正常
首先,我們簡要地回顧一下DDGI。DDGI 是Majercik 等人在Light Field Probe 算法的基礎上,結合硬件光線追蹤而提出的。同Light Field Probe 一樣,DDGI將場景的輻射度信息和幾何信息編碼到均勻分布的探針中。而與Light Field Probe 在場景初始化時預計算探針存儲的信息不同的是,DDGI 會動態地根據場景中變化的幾何和光源,動態地更新每個探針中存儲的數據。其更新過程如圖3。

圖3 探針信息的更新
在生成光線階段,DDGI 采用了最普通的均勻生成光線的方式。這種方式在大部分情況下均適用,但當每個探針處發射的光線數目較少時,極可能造成閃爍等偽影。本文希望通過重要性采樣的方式規避掉這些問題。在更新每個探針存儲的數據時,DDGI 通過混合的方式,通過控制混合的α值將新的數據與前一幀的數據結合起來。如公式所示:

著色點最終的間接光照計算,DDGI 相較于Light Field Probe 一樣中的計算方式也作出了一些改變。籠統來說,為了能讓DDGI 動態場景下具有更強的魯棒性,Majercik 等人綜合參考了一些光線追蹤和陰影貼圖的文獻,在計算包含著色點的八個探頭對應的輻照度之后,結合著色點的位置以及探針的位置,計算對應的插值權重,具體包括:
(1)通過一個合理設置的閾值,當探針處于著色點切面以下時,將此探針的插值權重設置為0;
(2)采用基于感知的權重來解釋人類視覺系統對其他黑暗區域(即漏光)低強度照明的敏感性;
(3)采用方差陰影貼圖算法描述的均值和方差偏差的切比雪夫插值用于探針和著色點之間的可見性判斷,以便能更好地對探針中的輻照度進行濾波;
(4)根據與著色法線和探針方向來偏移著色點:這通過遠離潛在的陰影和非陰影不連續的區域來提高基于可見性的插值權重的魯棒性;
(5)根據著色點和探針中心之間的距離,使用上述計算得到的權重執行標準的三線性插值。
總的來說,DDGI 改進了傳統的基于探針的輻照度插值算法,使其能夠支持動態場景和動態光源。但其存在當探針處發出的光線數目較少時產生閃爍等問題。
分層樣本扭曲[6]是一種讓樣本點的分布與某個函數相匹配的技術。假定我們可以拿到前一幀的輻射度信息(通過小波變換或者生成Mip-Map,本文以Mip-Map 作為例子講解),則我們可以通過分層樣本扭曲,將給定的均勻分布的樣本點,扭曲成符合該輻射度的分布,如圖4 所示。
首先,我們需要從Mip-Map 最糙的一級開始(分辨率為2×2),首先對于每一行,我們先計算行分界線。在本文的例子中,上面一行的平均輻射度為80%,下面一行的平均輻射度為20%,因此我們可以得到相應的分界,如圖5 所示。

圖4 HSW的基本圖示

圖5 縱向Warping
隨后,對每一行分別進行同樣的處理,如圖6 所示。在本文的例子中,上面一行靠左側的平均輻射度為75%,而靠右側的平均輻射度為25%。同樣的,我們也需要對下面一行進行分層樣本扭曲。

圖6 橫向Warping
通過HSW,我們得到了一個根據2×2 重要性函數分布的樣本點集合,且在每個象限中的樣本點均為均勻分布。分層樣本扭曲會遞歸的在每個Mip-Map 層級進行,當扭曲過程結束以后,我們將可以得到跟重要性函數相同的樣本點集合。
概括上來說,我們只需要改進圖3 生成光線的策略(以重要性采樣的方式)即可。因此,我們需要將探針更新的流程改成圖7 示。首先,我們可將上一幀探針采樣得到的結果進行分層樣本扭曲,以確定每一個探針需要在哪些立體角內發射更多的光線,以及在其他對應的立體角發射較少的光線。在采樣方向確定以后,我們仍然需要在這些方向上應用光線追蹤,以確定這些方向所擊中場景中點的相關信息(例如法線、材質信息等),形成類似G-Buffer 的結果。然后我們需要對生成的G-Buffer 進行直接光照和間接光照的著色,所得到的結果將會用于更新探針的輻照度,且會被用于下一幀的分層樣本扭曲。
其中比較困難的一步是如何使用GPU 實現分層樣本扭曲。在過去由于GPU 的種種限制,分層樣本扭曲往往是是現在CPU 端的。由于CPU 與GPU 之間相互傳遞數據需要涉及內存與顯存之間相互拷貝數據,這一過程往往很耗時,因此我們需要在GPU 端實現分層樣本扭曲。本文的解決方案是將分層樣本扭曲并行在探針級別,并采用計算著色器實現。這樣我們可以在較短的時間內實現重要性采樣,得到最終的采樣結果。后續更新探針的輻照度信息以及用更新后的探針結果進行著色的過程與DDGI 差別不大,只是由于我們采用了重要性采樣,可以適當調低更新過程中使用的α的大小,同時畫面保持無抖動狀態。

圖7 結合重要性采樣的探針信息更新過程
本文所有實驗的硬件設備如表1 所示。

表1 實驗硬件
圖8 展示了加入重要性采樣以后,渲染的結果(分辨率為1920×1080)。最左一列表示直接光照結果;中間一列表示加上漫反射全局光照的結果;最右側一列表示加上高光全局光照的結果。對應的性能數據如表2 所示。

圖8 復雜場景下渲染的結果

表2 性能數據
本文就DDGI 在采樣不足的情況下可能出現閃爍的偽影進行研究,采用重要性采樣的方式解決這一問題,該改進方式能夠有效地緩解這一問題。將來的研究將主要從以下兩個方面進行:
首先,該算法現階段并沒有有效地將光澤反射的全局光照結合進去,因此只能通過其他算法去計算這一效果;其次,現階段對探針的更新是暴力地更新場景中的所有探針,這種暴力更新策略其實浪費了大量計算資源(例如當前相機只能看見整個場景的某一部分,但卻對所有探針進行更新),我們僅需要對視錐體內部以及靠近視錐體的一部分探針進行更新。在后續的研究中,希望可以對著兩點進行改進。