本文主要內容包括:光追硬件、RTRT應用、降噪的基本思路、Filtering、SVGF、RAE
1. Real Time Ray Tracing
1.1 硬件上的提升
RTX其本質上只是硬件的提升,並不涉及任何算法部分。
GAMES101中提到光線要經歷BVH或者KD-tree這種加速結構,也就是做一個樹的遍歷從而快速判斷光線是否與三角形求交,這部分對於GPU來說是不好做的。所以NVIDA在顯卡加裝了一個用來做光追的硬件,用於光線與場景的求交,來幫助我們每秒可以trace更多光線。
即使每秒能trace 100億根光線,但在除以分辨率和幀數后,再拋去其它后處理和其它Shader的消耗后,只能做1spp:
1spp 做了以下內容:
- primary hitpoint(從camera出發打出一根光線打到的交點)
- shadow ray(primary hitpoint 和光源之間連接進行light sampling並判斷是否有遮擋)
- secondary ray(在Hitpoint根據材質采樣出一個方向打出一根光線,他會打到一個物體上從而得到secondary hitpoint)
- secondary shadow ray(從secondary hitpoint與光源連接判斷是否會被光源看到)
蒙特卡洛路徑追蹤在64 spp得到的生圖仍然有很多噪點,1spp完全沒法看。
所以RTRT最核心的技術是: 降噪。
1.2 RTRT 的應用
一張圖概況:
2. 降噪的基本思路
下圖是1spp降噪之后得到的結果:
因為降噪之后不能糊成一片,也不能消耗太多時間,所以排除了一些以前的方法:
- Sheared filtering serise(SF,AAF,FSF,MAAF,...)Sheared方法不行
- Other offline filtering methods (IPP,BM3D,APR,...)離線方法不行
- Deep learning series(CNN,Autoencoder,...)深度學習不行
工業界最終采用的方法是基於temporal的降噪,核心方法:
首先假設整個看的場景的運動是連續的,就是camera以某種軌跡看向不同的物體,幀與幀之間有大量的連續性;
motion vector,它是用來告訴我們物體在幀與幀之間是如何運動的,也就是圖中的A點在motion vector下可以知道在上一幀里A點對應的位置B點。
- 我們認為當前幀是需要去進行filtering,前一幀時已經filtering好的;
- 利用motion vector來知道當前幀某一點在上一幀的對應位置;
- 由於認為場景運動是連續的,所以shading也是連續的,上一幀得到降噪好的結果比如顏色之類的,可以在當前幀復用,相當於增加了spp,但並不是簡單的上一幀1 spp+當前幀1 spp,由於是一個遞歸,因此上一幀也復用了上上一幀的結果,因此spp其實是很多的,可以理解為一個指數衰減,每一幀都有百分比貢獻到下一幀;
2.1 G-Buffer
G-Buffer,全稱Geometric Buffer。將屏幕采樣時可以拿到的信息存到紋理中,這些紋理稱為幾何緩沖區
2.2 Back Projection
透過當前幀(frame i)中藍點這個像素我們所得到的點的世界坐標,投影到上一幀(frame i-1)中對應的是哪個像素。
首先計算當前像素的世界坐標:
如果G-Buffer里有,可以采樣得到;沒有的話可以通過MVP和視口變換的逆矩陣得到:
當前幀世界坐標乘以幀移動的逆矩陣就得到了上一幀中這個點的世界坐標:
將世界坐標轉換回屏幕坐標:
現在可以結合當前幀(noisy的圖)和上一幀(沒有noisy的圖),最簡單的方法就是線性blending在一起,比如上一幀的結果 0.8 + 這一幀的結果 * 0.2得到新的結果,公式如下:
~ : unfiltered 表示沒有filter噪聲挺多的內容
- : filtered 沒有噪聲或者噪聲比較小的
2.3 Temporal Failure
時間上的復用存在的問題
2.3.1 Switching scenes
場景切換或者換光源的時候,完全沒有上一幀信息,即使有也是不准確的
2.3.2 Walking backwards in a hallway
向后走,屏幕空間上下左右四個邊會有屏幕之外的內容進入,這些部分是沒有上一幀信息的
2.3.3 Suddenly appearing background
本來被遮擋的部分突然能看見了,同上
2.3.4 殘影
移動攝像機,被儲物櫃擋住的牆面出現,上一幀參考比例較大,攝像機移動速度較快,這種殘影比較明顯。
工業界有兩種解決辦法:Clamping和Detection,可以單獨使用也可以結合。
Clamping方法主要思想是降低顏色差異,將上一幀的顏色與當前幀的顏色差控制在一定范圍內:
Detection方法主要思想是判斷到底要不要采用上一幀的結果,判斷前后兩個次屏幕采樣是否來自同一個物體,如果不是就不用了。
殘影問題同樣存在於陰影。
3. Filtering
濾波所做的概括起來就是做了一個模糊的操作,把一些噪聲消除,也就是將一個比較noisy的圖,降噪從而得到一個干凈的圖:
上圖中使用的是低通濾波,用於光追降噪來說有兩個問題:
- 高頻信息中可能包含有用的信息,抹掉會導致信息丟失;
- 低頻信息中也可能包含噪聲;
3.1 高斯濾波
一般來說我們為了給光線追蹤由於蒙特卡洛產生的噪聲降噪時,用的是高斯的濾波器,它類似於正態分布,中心值高,向兩邊衰減:
偽代碼:
For each pixel i
sum_of_weights = sum_of_weighted_values = 0.0
For each pixel j around i
Calculate the weight w_ij =G(|i - j|, sigma)
sum_of_weighted_values += w_ij *C^{input}[j]
sum_of_weights += w_ij
C^{output}[I] = sum_of_weighted_values / sum_of_weights
3.2 雙邊濾波
高斯濾波可以得到了一個整體都被模糊的結果,但是我們想讓邊界仍然銳利,因此除了高斯我們需要其他的方法來幫助我們保留下邊界的這些高頻信息,因此引入了雙邊濾波(Bilateral filtering)
雙邊濾波認為顏色變化特別劇烈的地方認為是邊界,如果二者差距不是特別大我們繼續用高斯處理j到i的貢獻。如果像素i和像素j之間的顏色值差距過大,我們認為這兩個像素分別在邊界的兩邊,從而讓像素j給i的貢獻變少,具體做法是在高斯的濾波核上加一些東西:
在這里i和j代表一個像素,k和l代表另一個像素;I(i,j)表示第一個像素的值,I(k,l)表示第二個像素的值;分母是距離的平方。等式的第二部分的意義在於,如果兩像素差異過大,則減少像素(k, l)對(i, j)的貢獻。
上圖右邊是經過雙邊濾波后結果,可以發現,既保留了邊緣的高頻信息,有抹平了山峰、湖泊、樹木的低頻信息。
3.3 聯合雙邊濾波
Joint Bilateral filtering,可以結合出了顏色之外的更多信息進行濾波,比如法線方向、場景深度、Shadow Map等。
聯合雙邊濾波使用的濾波核不局限於Gaussian,可以使用指數或者Cos等,每個人都可以有不同的操作:
下圖中A和B可以通過深度判斷不接近、B和C可以根據法線、D和E根據Shadow Map,以此類推:
3.4 濾波效率優化
濾波核越大、消耗越大;一個64*64的濾波核在不優化的情況下每個像素都需要采樣4096次。工業界流行兩種解決辦法
3.4.1 Separate Passes
拆分實現,將濾波拆到兩個Pass,水平方向,垂直方向各一次;這樣將采樣數從\(N^2\)降到了\(N+N\):
高斯函數在數學上就是拆開定義的:
但是理論上這種做法只適用於高斯,雙邊濾波或者聯合雙邊濾波\(x\)和\(y\)不容易拆出來;實際上只要范圍不是太大,可以硬拆。
3.4.2 Progressively Growing Sizes
大體方法是先用一個逐步增大的filter,比如先用一個小的filter,然后用中號的filter,最后是大號的filter,通過多趟的filter得到N*N的filter得到的結果:
也是多Pass操作,假設每趟都是5*5的filter,第一趟步長\(2^0\)、第二趟間隔\(2^1\)、第三趟間隔\(2^2\)、第四趟間隔\(2^3\)、第五趟間隔\(2^4\)。第五次的時候因為filter size是5,所以相當於最終得到了filter size 64的結果。
逐步增大filter而不是直接用一個pass做間隔16的樣本式為了保留低高頻信息(用更大的filter == 除掉低頻信息);
采樣 = 重復的搬移頻譜;采樣間隔越大頻譜間隔越小,但是因為Pass1去除了\(5*5\)范圍內的高頻信息,Pass2的采樣正好覆蓋了了Pass1頻譜的收尾,所以避免了加大步長的走樣問題。
3.5 Outlier Removal
用蒙特卡洛方法渲染一張圖時,得到的結果會出現一些點過亮或者過暗,這些過亮或者過暗的點如果經過使用filter這種降噪的方法去處理的話,會導致畫面有亮斑或暗斑,所以必須在filter之前處理掉。
3.5.1 Outlier Detection and Clamping
Detection:首先通過給對每個像素周圍的一定區域采樣,計算方差,如果方差超過一定范圍就認為它需要進行處理;
Clamping(outlier removal):對篩選出來的像素進行Clamp
3.5.2 Temporal Clamping
公式如下:
對於這個公式的解釋在上文2.3.4 殘影部分,這種方法並不是解決Outlier的辦法,是一個對noisy和殘影的tradeoff。
4. RTRT采用的濾波方法
4.1 Spatiotemporal Variance-Guided Filtering
SVGF方法與時空上降噪的方法差不多,加了一些方差分析和tricks,也是一種聯合雙邊濾波:SVGF-Joint Bilateral Filtering。
4.1.1 Depth
由於exp(x)是返回e的x次方,由於公式返回的是-x次方,所以差異越大,貢獻越小;
分母中的\(|\nabla z(p) \cdot(p-q)|\) 代表 深度的梯度 * 兩點間的距離;
\(\epsilon\) 的作用是因為我們filter時候考慮一個點Q周圍所有的點P,也包括這個點Q,因此它是有可能為0的,避免分母為0的情況,而且如果兩點足夠接近會導致最后的數值太大,為了避免一些數值上的問題加上一個\(\epsilon\);
\(\sigma_{z}\) 是一個用來控制指數衰減的快慢的參數,或者理解為控制深度的影響大還是小。
理論上A和B互相會有很多貢獻,但是如果單純看深度,可能會導致貢獻偏差變大。
4.1.2 Normal
\(\sigma_{n}\) 是一個用來控制指數衰減的快慢的參數,或者理解為控制法線的影響大還是小;
這里采樣的法線並不是應用了凹凸紋理的效果,因為應用之后同一個面的法線方向都有較大差異。
4.1.3 Luminance
在考慮顏色差異時,最簡單就是應用雙邊濾波里給的顏色差異來考慮,比如我們將RGB轉換為grayscale(灰度),這種顏色我們稱其為luminance,只是一個名字,我們就認為其是顏色。
比對任意兩點間的顏色差異,如果顏色差異過大,則認為靠近與邊界,此時A和B的貢獻不應該互相混合起來,A不應該貢獻到B,B也不應該貢獻到A。
分母中的\(\operatorname{Var}\left(l_{i}(p)\right)\) 表示計算點P周圍一定范圍內的方差,比如7x7;同時可以利用temporal得到上一幀的variance 進行一個差值;
\(\sqrt{g_{3 \times 3}\left(\operatorname{Var}\left(l_{i}(p)\right)\right)}\) 則表示對周圍3x3區域內的方差做一次空間上的濾波得到最終的variance;
總結來說就是spatial filter → temporal filter → spatial filter 從而得到P點精准的variance
最終SVGF得到的結果不錯,但它無法解決temporal導致的殘影問題。
4.2 Recurrent AutoEncoder
RAE是指Recurrent AutoEncoder,用RAE這么一種結構對Monte carlo路徑追蹤得到的結果進行reconstruction,也就是對RTRT做一個filter從而得到一個clean的結果。
這種方法基於神經網絡,輸入noisy的圖和G-buffer,自動利用temporal的結果。
下面式一張兩種濾波手段的對比圖:
引用
GAMES 202
圖片來自GAMES 202 PPT
https://zhuanlan.zhihu.com/p/387619811
https://zhuanlan.zhihu.com/p/389335568
https://zhuanlan.zhihu.com/p/397575842