蒙特卡洛光線追蹤基礎 - 實時光線追蹤的降噪

最近的 DLSS 3.5 可謂是實時光追降噪領域的革命,它的 Ray Reconstruction 技術(shù)其實就是一種 AI 降噪器,替換了原來的時空濾波技術(shù)(原本類似 SVGF 的方法)。所以趁著這個機會我就先把這個系列文章更新了,主題就是實時光追的降噪,最后會延伸到現(xiàn)在的 DLSS 3.5 技術(shù)。
上篇文章:

提到了蒙特卡洛光線追蹤的兩大重要基礎——渲染方程和概率密度函數(shù)?,F(xiàn)在我們就來討論另一個重要概念,就是降噪(denoise)。通過這篇文章,你將看到降噪在光線追蹤中起到的重要作用,尤其是在游戲領域,也就是實時光線追蹤上的重要應用。
首先什么是濾波我們要說一下。顧名思義,濾波(Filter)就是對信號中特定波段頻率濾除的操作,是抑制和消除信號干擾的一項措施。而噪聲(noise)則是信號干擾的一種體現(xiàn),為了去除噪聲,我們就要進行濾波。

上篇文章我們提到蒙特卡洛光線追蹤的本質(zhì),就是采樣或多次采樣蒙特卡洛積分來接近收斂到正確結(jié)果。然而我們的采樣數(shù)? 時才會完全收斂,其實除了每像素采樣次數(shù)之外,還有一個叫反彈(bounce)的重要概念。
我們這里看一下渲染方程的諾依曼級數(shù)展開。這里,我們把渲染方程寫成以下形式:
其中? 是線性算子。
接著,我們再改寫一下這個表達式:
其中 1 是單位算子,我們可以再轉(zhuǎn)換為這個形式:
通過這個式子你也能看出要用數(shù)值方法快速求出渲染方程的解析解幾乎是不可能的。
其中? 對應光線反彈的次數(shù)。一般地實時光線追蹤技術(shù)里?
?, 再高下去的增益不明顯(經(jīng)過反彈之后光能會大量衰減)并且開銷呈指數(shù)上升。

說完了實時光追在渲染上的一些注意事項,我們接下來進入降噪環(huán)節(jié)了。
對光線追蹤的結(jié)果進行降噪,對幾何多邊形抗鋸齒,對紋理做反走樣(例如各向異性過濾)都屬于濾波。

右圖就是通過每像素發(fā)射 32?根光線(也稱每像素采樣 32?次,?32?spp)去采樣渲染方程得到的結(jié)果。左圖則是經(jīng)過了時間性濾波得到的結(jié)果。這里也間接地說明了濾波不只是針對空間的,時間維度上也可以做濾波。例如著名的時間性抗鋸齒(TAA)就屬于一種時間性濾波。
對于實時光線追蹤來說,找到一種合適的降噪方式是非常重要的。因為目前消費級光線追蹤硬件的性能只能滿足于每像素發(fā)射 1-2 根光線去采樣。
所以所謂的實時光線追蹤的難點完全不在于渲染技術(shù)(渲染方程,蒙特卡洛無偏估計,BSDF 模型),它們的原理和工業(yè)界用了很多年的離線渲染是一致的,已經(jīng)十分成熟;
真正的難點在于后期做的重建(reconstruction)工作(降噪,升采樣,性能優(yōu)化)。
好,接下來我們就正式進入實時光追的降噪了。它的本質(zhì)就是通過濾波算法來消除高頻的噪聲。高頻就是信號的變化幅度很大,看上去密密麻麻的。

一般性定義:
我們定義一個帶有噪點的圖像?,這個作為降噪的輸入數(shù)據(jù)。
另外,降噪的算法方面,我們定義一個濾波核 (kernel)?,?它可以有很多種,用來改變像素,我們簡稱 “核”。
最終圖像為?。

我們先從簡單的高斯濾波(Gaussian Filter)說起,它最常用來做模糊效果。了解了這一整套流程之后,你將會更理解實時光追的另一種基于聯(lián)合雙邊濾波的方法。
用高斯濾波的核對圖像做卷積可以使得圖像的高頻信息變成低頻的,最終結(jié)果就是圖像變得模糊了起來。
高斯提出的正態(tài)分布大家都知道吧。?維空間的正態(tài)分布為:
令?,則二維表達為:
其中模糊半徑??與橫縱坐標?
有??
?的關系,這樣一來我們可以得到:
通過這個方程,我們可以生成一個高斯核。不過一開始生成的高斯核是一堆浮點數(shù)組成的,我們要進行定點化。以 的為例,因為在定點后我們需要做歸一化(normalization),必須除掉這個數(shù),?所以選擇 2^8 也就是 256 做定點。
最后得到的核長這樣:
它還可以拆成兩個一維的核,這樣?? 的采樣就變成了?
次,節(jié)約了性能。
這是一個逐像素進行的操作。設 是原本像素,
?是周圍像素,則理論上需要考慮所有?
和?
自身的貢獻值。
但實際上不必考慮所有像素周圍的所有信息,因為根據(jù)正態(tài)分布圖象,兩邊延伸的值非常小。在這里可以當成沒有像素貢獻值。

所以編程時只需稍微設置下??就可以了,一般選擇
。如上圖,這時候的值是很小的。
好了,接下來看下高斯濾波的效果:

顯然,高頻信息被干掉了。左邊有肉眼可見的高頻噪聲,右邊沒有了。
上面我們以高斯濾波,高斯核作為引例來解釋了濾波上的一些東西。接下來我們就要回歸實時光追這邊來了。如果你在剛才已經(jīng)形成了初步認知,那么接下來的東西也會比較簡單。
我們提到,濾波可以有很多種。接下來我們介紹一種濾波,叫做聯(lián)合雙邊濾波(Joint Bilateral Filtering),這是目前實時光追中 SVGF 降噪的基礎。
它有很多優(yōu)點,比如不需要像高斯濾波那樣要考慮到歸一化的問題,聯(lián)合雙邊濾波這個過程本身就已經(jīng)做了歸一化了。
聯(lián)合雙邊濾波相比于雙邊濾波,優(yōu)化了相似性權(quán)重模板。什么是雙邊濾波呢?我們知道高斯濾波最終的結(jié)果全是低頻的,這肯定是不行的。為了視覺觀感,去掉低頻噪聲的同時我們也要保留高頻信息。
雙邊濾波的核心就是:如果兩像素的顏色差異較大,則降低周圍像素? 對原本像素?
的貢獻。
所以我們在高斯濾波的基礎上來表示顏色差異,以此實現(xiàn)雙邊濾波。這樣一來,像物體的輪廓等高頻信息就沒有被破壞。
而聯(lián)合雙邊濾波則能使用更多信息來做濾波,除了顏色之外還有?Depth(深度), Normal(法線)信息。這些一般都是通過光柵化來生成的,本身就不帶噪點。這對使用聯(lián)合雙邊濾波來降噪是很好的。

例如:
A,B 兩點就可以通過深度信息來判斷貢獻(一個在后面的墻上,一個在磚塊的前面);
B,C 兩點可以通過法線來判斷貢獻(一個法線朝著正面的墻,另一個朝著側(cè)面的墻);
D,E 兩點就可以憑借顏色信息來判斷了。
這樣我們就可以確定貢獻值,它們互相之間的貢獻基本等于沒有,所以我們就可以保留住它們不進行模糊濾波。
這樣一通操作下來,我們輸入的信息多了,控制濾波的因素就多了,所以我們就需要一個很大的核(有可能會達到 的大?。@開銷就過于龐大了。
其實我們之前把那個二維高斯核拆成兩個一維核就是一種解決方案,但是理論上雙邊濾波是不能這樣拆的,所以我們另辟蹊徑:

如上圖,我們選擇漸進地增大濾波的大小。
第一層 ?使用?
的核,然后第二層繼續(xù)使用?
?的核算出第三層的中間像素,連續(xù)算5層,每一層都間隔?
個像素,直到
,這樣就能將原本濾波的一個像素需要?
的核變成?
的了,大幅節(jié)約了性能(采樣次數(shù)
)。
但濾波不是萬能的。輸入圖像可能少許存在一些小的白色亮點(outlier),其實這是求解蒙特卡洛積分導致的問題,亮度可能會出現(xiàn)大于 1 的情況。
但是做濾波的過程中,這些 outlier 會越來越大,遠超過 1,影響到的周圍像素導致出現(xiàn)比較明顯的大白點了,如下圖。所以我們需要一些手段在濾波之前就去掉這些 outlier。

方法也很簡單。我們分為尋找和消減兩個階段:
尋找階段
遍歷一個像素周圍的?
的區(qū)域 (
),算出的均值?
?和方差?
?。
如果這個像素的值在?
?范圍外(一般?
),則判定該像素為 outlier。
消減階段
我們并不是要刪除這個像素,因為它只是亮度值有問題。
所以我們只需把亮度值給它 clamp 到?
? 即可。
但是這樣顯然違背能量守恒,因為人工調(diào)整了亮度值,這樣一來就違背了物理規(guī)律。
當然我們也可以簡單粗暴地直接提升每像素發(fā)射光線的數(shù)量來減緩 outlier 的出現(xiàn)頻率,但對于實時光追來說這是極其昂貴的。就算是賽博朋克 2077 的超速光追,也只是達到了 2 spp 的數(shù)量級,然而這已經(jīng)是游戲領域里最高的了。
然后我們來講一講時間上的濾波。剛剛講了這么多,你應該能發(fā)現(xiàn)我們一直圍繞著空間的角度來展開降噪的。單有空間信息的效果是肯定不夠的,我們還要時間維度上的。
所以,我們現(xiàn)在就進入時間濾波(temporal filtering)了,并且結(jié)合空間濾波(spatial filtering)來理解我們現(xiàn)在已經(jīng)應用的時空濾波(spatiotemporal)的降噪方法。

首先,要做時空圖像信號的濾波,我們要明確一個很重要的概念叫 “復用”(reuse),為什么呢?因為在實時渲染里,每秒都要渲染幾十上百幀,細分到時間軸上,每相鄰兩幀的變化往往不大,所以有很多信息是可以下一幀直接拿來用的。
所以這里有一個很重要的概念,叫做運動矢量(motion vector),它描述了場景內(nèi)容的變動情況,也就是說我們可以通過運動矢量來找到上一幀的位置信息。

這里我們使用?BackProjection 方法來尋找運動矢量,將第? 幀著色點的屏幕空間坐標轉(zhuǎn)到世界空間,然后再把第?
幀的世界空間坐標轉(zhuǎn)到屏幕空間上來,這樣就得到了運動矢量。
P.S. 如果可以在 G-Buffer 里直接拿世界空間坐標的話那就不用轉(zhuǎn)換了。物體運動時注意做一遍逆矩陣。
好了,拿到運動矢量了,可以做時間性的降噪了。怎么降呢?對了,剛剛提到了復用,那么我們就可以復用上一幀已經(jīng)降噪過的信息來做線性插值了,而運動矢量在這里的用處就是提供復用幀信息的 “指導”。
我們在前面定義了:帶有噪點的圖像?,這個作為降噪的輸入數(shù)據(jù),算法方面定義一個濾波核?
,最終圖像為?
。
則空間上的降噪可以表示為:
空間上降噪的具體辦法,我們已經(jīng)花了大篇幅來討論了。接下來就是疊加上時間維度的東西了,則時空上的降噪可以表示為:
通常情況下,插值因子?。
但是又引出了新的問題,例如快速轉(zhuǎn)動視角導致的顏色信息不連續(xù),遮擋位移導致出現(xiàn)上一幀不存在的顏色信息等等。這時候盲目地做疊加就會產(chǎn)生各種 artifact 了。

所以我們要做一個很重要的工作,叫做 Temporal Clamping(不知道怎么翻譯)
回到這個表達式:?上來,
是上一幀的信息,我們沒有做任何處理。
實際情況下,上一幀的部分信息和下一幀可能截然不同,所以我們必須進行調(diào)整。
如果顏色差異過大,那么就把?? 給 clamp 到?
?的范圍來,這個值域在前文消減 outlier 的方法也提到過,它代表著當前幀的范圍。
不過 Temporal Clamping 是一種需要考慮權(quán)衡的做法,因為這里其實就需要考慮要保留更多鬼影還是更多噪點,如果鬼影少,那么噪點就明顯,反之亦然。

到這里,我們的實時光線追蹤降噪的基本原理就差不多結(jié)束了。接著我們再來看工業(yè)界常用的?SVGF,目前所有光追游戲都在使用它(或類似它的算法)來降噪。

SVGF 全名為?Spatiotemporal Variance-Guided Filtering;顧名思義,它是一種在時空濾波的基礎上對降噪算法做優(yōu)化。下圖是 SVGF 的算法目標和要求,來自 NVIDIA 研究科學家,也是這篇論文的合著者之一?Edward (Shiqiu) Liu 的一篇知乎文章(zhuanlan.zhihu.com/p/28288053)

和我們之前討論的時空濾波不一樣的是,SVGF 添加了方差信息作為引導。

SVGF 雖然使用了前文提到的雙邊濾波技術(shù),但是它沒有使用高斯核,我們之前也提到過核有很多種,不要求是完全遵循正態(tài)分布,只要是個逐漸衰減的模型都可以,比如?也可以拿來生成卷積核。
和之前我們討論的普通時空濾波一樣,SVGF 同樣也使用了深度 (z-depth),法線 (normal),顏色 (luminance) 這三個信息來指導濾波。SVGF 最大的特點就藏在 V 這個字母里。V 就是 Variance(方差)的意思,SVGF 在顏色權(quán)重上做了方差估計。
不難看出,它使用了? 來判斷?
兩點的深度差,權(quán)重值隨著深度差值的增大而減小,并且符合一個逐漸衰減的模型。衰減系數(shù)?
?控制著衰減的大小,而?
?是為了防止?
而存在的一個很小的數(shù)。
接下來則是考慮法線:
根據(jù)我們高中就學習過的向量點乘知識,這顯然是一個余弦函數(shù)的衰減模型。你看,沒有用高斯分布模型吧。其中??也是一個衰減系數(shù)。
最后就是顏色方面的處理了。之前說到傳統(tǒng)的聯(lián)合雙邊濾波,它是通過直接比顏色灰度值來確定差異的。這個方法不準確,因為圖像本來存在很多噪聲,一些比較亮或者比較暗的,不太正常的像素會導致權(quán)重值出現(xiàn)大的偏差。
所以 SVGF 在這里就做了方差估計:
首先在空間上計算??的方差,就像我們之前消減 outlier 那樣做;然后再在時間上利用運動矢量再來求個?
?的方差,最后再在空間上求另一個?
的方差,最后開平方得出標準差。
這樣一通操作下來,我們就能得到一個比較準確的標準差了,相對于傳統(tǒng)雙邊濾波去直接比灰度值要靠譜不少。這一套求方差組合拳的主要作用就是能較為準確地確定兩點間的貢獻關系,舉個例子,如果這里的標準差越大,就說明噪聲越嚴重,一般在處于陰影的地方比較常見,那么就可以確定它不該貢獻到那些被更多的光照射的,或者比較亮的地方。

從左到右:1spp 輸入圖像,4096 spp 參考圖像(Ground Truth),SVGF 降噪圖像,傳統(tǒng)雙邊濾波圖像。可以看出 SVGF 比較接近參考圖像了。
但是 SVGF 也有一個致命問題,那就是運動場景適配不完善。尤其是對 glossy 材質(zhì)的反射表面,著色延遲以及細節(jié)缺失問題相當嚴重。

因為 SVGF 依賴于運動矢量,而像陰影,半透明等著色信息是沒法生成運動矢量的,所以會造成比較嚴重的視覺滯后。不過在 NVIDIA RTX 時期,SVGF 的實現(xiàn)已經(jīng)被大幅優(yōu)化,至少現(xiàn)在的光追游戲不會看到像這樣的 artifact(評論區(qū)有 NV 的大佬,表示近期的技術(shù)改進了置信度緩沖):

然而 SVGF 的方法仍然干掉了很多畫面細節(jié),這使得?NV 專門研究了一種叫 ReSTIR GI 的全局光照重采樣算法來改善給輸入降噪器的原始數(shù)據(jù)質(zhì)量。

不過最近 NV 的降噪技術(shù)有了新的成果,也就是昨天 DLSS 3.5 Ray Reconstruction 的實現(xiàn)。它是經(jīng)過 DGX 超級計算機進行 5 倍于 DLSS 3 訓練算力的一個深度網(wǎng)絡模型,并且運行在 Tensor 管線上。
它拋棄了時空濾波算法,而采用了深度學習,已經(jīng)不是一條賽道上了的東西。

和 SVGF 相比,DLSS 3.5 使用訓練好的深度神經(jīng)網(wǎng)絡來指導降噪。這讓我想起了 FSR 1 和 DLSS 1 的關系,一個通過人為調(diào)整的固定算法做上采樣,一個是基于深度學習的上采樣。
并且 DLSS 3.5 的 Ray Reconstruction 是跑在 Tensor Core 這種特化電路上的,速度比在 CUDA?通用計算核心上跑的 SVGF 還要快一點,意外地提升了些許幀數(shù)。大概 10% 左右。
Rendering 的潛力快被挖干,現(xiàn)在是 AI 的天下了,老黃也開始在 SIGGRAPH 上賣起了計算卡。
References
[1]Kajiya, and? T. James . "The Rendering Equation." ACM?Computer Graphics 20.4(1986):143-150.
[2] Schied, Christoph , et al. "Spatiotemporal variance-guided filtering: real-time reconstruction for path-traced global illumination." High Performance Graphics ACM, 2017.
[3] Ouyang, Y. , et al. "ReSTIR GI: Path Resampling for Real-Time Path Tracing." Computer Graphics Forum: Journal of the European Association for Computer Graphics 8(2021):40.
[4] Lingqi Yan, GAMES202?- Real-Time High Quality Rendering,?Lecture 12/13 PDF.
[5]?NVIDIA,?https://www.nvidia.cn/geforce/news/nvidia-dlss-3-5-ray-reconstruction/, website.