Lecture 12 Real-time Ray Tracing

Telluluu發表於2024-09-01

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

\[\sim表示帶noise的當前幀,-表示不帶noise的上一幀 \]

  • 首先先對當前幀做一個特殊的降噪
    • \[\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
    • 但是無法解決螢幕空間問題,因為就是不知道螢幕外的資訊,無法解決

相關文章