Lecture 12 Real-Time Ray Tracing
Basic idea
sample per pixel PPS
1 SPP path tracing = $$\downarrow$$
- camera出發打到求出第一個交點(畫素上看到的點),這一步是primary ray(工業上實際用rasterization)
- 工業上這一步有一個技巧
- 將這一步改為光柵化
- 因為每個畫素都要從camera出發打一條光線看打到了什麼,這一步和光柵化做法一模一樣
- 並且光柵化更快
- 從第一個交點和光源做連線,做light sampling, 看是否可見(shadowing ray, primary visibility)
- 這一步與前一步實現的是直接光照
- 從shading point上進行取樣(secondary ray)
- secondary ray打到的點與光源連線,看是否能看到光源 (secondary visibility)
透過RTX硬體加速能夠做1SPP的光追(2080ti時代),但是得到的結果會有非常巨大的噪聲
所以RTRT最關鍵的技術是Denoising降噪
目標(1SPP情況下)
- 質量(無overblur、無artifacts,保證所有細節)
- overblur指濾波核過大,導致結果過於模糊
- 看起來奇怪的地方,是可見的bug
- 速度 一般每幀2ms以內,最多不超過5ms
這些要求達不到
- Sheared filtering series (SF, AAF, FSF, MAAF, ...)
- 離線濾波方法
- 深度學習系列 (CNN, Autoencoder, ...)
- 稍微複雜的網路跑一遍就得幾十到幾百ms了
工業界的做法,核心是Temporal
Key idea
- 認為前一幀是濾波好的,複用它
- 所有運動都是連續的,沒有突然的變化(實際上不可能)
- 使用motion vector找到上一幀的位置
- 透過這種方法相當於增加了SPP
- 並不是增加了1SPP,因為這是一個遞迴的思路,每一幀都利用上
- 是一個指數下降
- Spatial?空間上怎麼降噪?
Motion vector
G-Buffers
Geometry buffer 幾何緩衝區
- 渲染過程中可以免費得到的額外資訊
- 代價很小,可以認為免費(輕量級)
- 一般有每畫素深度、法線、世界座標等等
- 只有螢幕空間資訊
- G-buffer是第一趟光柵化代替光追時得到的
Back Projection
要求當前幀$$i$$中的畫素$$x$$在前一幀$$i-1$$中的位置,兩種做法都可以
-
當前幀$$i$$中的畫素$$x$$在前一幀$$i-1$$中的位置
- 從後項求前項
-
前一幀$$i-1$$中的哪個畫素包含當前幀$$i$$的同一個地方/點
- 從前項求後項
要求畫素的世界座標有兩種方法,二選一
- 直接從G-buffer中獲取(推薦)
-
\[s=M^{-1}V^{-1}P^{-1}E^{-1}x$$,這裡$$E$$是視口變換 - 要變回齊次座標,所以輸入不能是2D的螢幕座標,得是帶深度的齊次座標 - 注意視口變換沒有改變深度值 - 關於為什麼要乘以Model矩陣的逆矩陣,因為場景中的問題可能會移動,乘以當前幀這個物體的$M^{-1}$,找到`localPosition`,再乘以上一幀這個物體的$M$矩陣就能準確得到世界座標 \]
- 如果物體發生了運動,那麼運動向量$$T$$已知
-
\[s'\stackrel{T}{\rightarrow}s$$,則$$s'=T^{-1}s \]
- s是區域性座標系
- Motion Vector是兩幀同一個畫素的螢幕空間座標之差
-
- 該畫素在上一幀的對應$$x'=E'P'V'M's'$$
- 在計算機視覺裡求上一幀畫素位置的操作叫optical flow光流
- 圖形學的這種計算是準確的
- 而光流是基於內容的,不準確
- 這些操作都是在影像上的
- 物體移動後的光線資訊可能會改變
Temporal accumulation / filtering
於是就可以將當前幀有noise的圖和上一幀沒有noise的圖結合在一起
最簡單的做法就是做一個線性blending
- 首先先對當前幀做一個特殊的降噪
-
\[\overline C^{(i)}=Filter[\widetilde C^{(i)}] \]
- 無法僅依賴於當前幀的降噪,因為在1SPP單純降噪效果不夠
-
- 再做一個線性blending
-
\[\overline C^{(i)}=\alpha \overline C^{(i)}+(1-\alpha)C^{(i-1)} \]
-
- 如何平衡$$\alpha$$的數值?
- 一般取$$0.1\sim 0.2$$
- 說明$$80%\sim90%$$是來源於上一幀
- 如果兩幀之間光照變化,就不能依賴上一幀了
- 降噪後明顯變亮了?
- 實際沒有變亮,降噪前後是能量守恆的
- 原因是降噪前某些噪點的亮度超過顯示器範圍,被clamp到了1
- 所以顯得暗了
- 濾波絕對不會使一張圖變亮或者變暗
Failure cases
-
case 1: switching scenes 這是shading上的問題
切換場景、切換光照、切換鏡頭都會導致上一幀不能複用
需要一個burn-in period積累前幾幀的資訊
這裡是一個光源移動的例子,場景和camera沒有移動,所以motion vector是0,這樣沿用上一幀會導致陰影拖尾 (detached/lagging shadows)
-
case 2: 倒退著走(螢幕空間問題)
因為倒退著走時,越來越到的資訊出現在螢幕中,會導致新出現到螢幕中的點在上一幀找不到對應
如圖中倒退著走,越來越多的東西會出現在鏡頭中
-
case 3: 突然出現的背景 disocclusion問題 同樣是螢幕空間問題
當箱子移動後,右側當前幀藍點在左側前一幀對應的位置正確,但是在上一幀,這個物體處於被遮擋的狀態,導致其實找不到正確的資訊
這也是一種螢幕空間問題,因為這一點在上一幀被遮擋,根本沒有存它的資訊
-
那麼要將上一幀拆成不同深度嗎?
不要,開銷太大了
-
-
case 4: glossy reflection 在shading上的問題
反射物移動,反射接收物不動(地板),會導致反射光滯後
motion vector只反映了物體在幾何上的變化,在shading上的錯誤透過傳統的motion vector沒辦法解決
錯誤處理
-
無視錯誤,強行復用上一幀
- 造成lagging 拖尾
-
Clamping
比如failure case3中,造成拖影的原因是將上一幀錯誤的黃色用在這一幀白色的地方
那麼任何時候應用上一幀的值的時候,都先將上一幀的值拉近到當前幀的結果(Clamping),再去做blending,就看不出問題了
-
極端情況
- 如果拉的過大,太過偏離上一幀的結果,接近當前幀的結果,那麼用上一幀就沒意義了
- 取當前幀該點(空間上)周圍一個範圍,求出均值和方差,將上一幀沒有noise的值clamp到這個範圍內(均值$$\pm$$幾個方差 )
- 注意是將上一幀的結果拉到當前幀,如果將當前幀結果拉到上一幀,拖影就更嚴重了
-
當然會有噪聲,原本拖影的地方變成噪聲了
-
-
Detection
檢測要不要用上一幀的資訊
- 使用object ID
- 調整$$\alpha$$,非0即1,或者根據偏差的情況調整
- 上一幀沒有noise,當前幀有noise,調整後更多地依賴當前幀,noise也就更多了
- 儘可能增強或者增大filter
- 讓當前幀更糊了,不過總比噪聲好
-
兩種方法都相當於重新引入了noise
Temporal Anti-Aliasing (TAA)
Temporal accumulation / filtering和TAA 時間上抗鋸齒的概念基本等同
二者都是複用上一幀對應的位置,相當於提高一個畫素的取樣數,從而減少鋸齒
*一切利用Temporal的方法都差不多,包括DLSS
- Temporally Reliable Motion Vectors for Real-time Ray Tracing
- Eurographics (EG)
- 這篇論文提出了一些motion vector,讓它可以追蹤陰影、反射、遮擋出現的變化,從而部分解決前面提到的Shading上的failure
- 但是無法解決螢幕空間問題,因為就是不知道螢幕外的資訊,無法解決