天天看點

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

gdc19年,一直開發地鐵系列的4A games;

4A games是成立于2006年,烏克蘭開發商,一直做metro系列遊戲,三個大版本,中間兩個重制版。

技術上一直metro是比較激進的,是硬體廠商show技術的常客,這次raytracing也沒有缺席.

一些細節的效果對比可以看這裡:

https://www.bilibili.com/video/BV1M5411s7v4/

本文聊得是gdc19上4AGames的talk,也是個人認為到目前為止(2020.5.6)講遊戲中使用raytracing中最好的一篇。

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

我們可以看到從整體上看,rt版本的光照更加的完整自然。

用RayTracing做了什麼

4AGames是用stochastic的方式,用raytracing做了RTAO,RTGI

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

這裡也代表了raytracing技術帶來的幾個明顯提升點:

  • RTAO對比ssao,實體正确的多
  • RTGI對比voxel based gi:在同等效率下,精度&trace範圍上有很大的優勢

    這裡也要補充下,如果實際玩遊戲的話,會發現提升其實一般,這個在digital foundry裡面會有盡可能的充分比較,但是在玩家視角來看,可能還是提升有限。

    這裡很重要一點是受限于地鐵遊戲的畫風非常的“頹廢感”,導緻光照優勢沒法充分展現,但是拆開到ao到gi,可能看到單項上的提升是有限的。

    可以說在metro中,光追技術開始充分展現了它的潛力,metro也做了遠不止是把光追feature用用的程度,有了很不錯的探索。

btw:

stochastic的方式,就是以一些随機分布的方式在空間上低頻采樣,然後再通過denoise來複原畫面的方式:

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

(如圖,左邊是stochastic根據一些機率分布函數在空間中采樣計算,然後結合空間&時間(temperal)資訊做denoise,就是右邊的結果了)

pipeline

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

這裡是整體的pipeline。

這個部分介紹整體pipeline的情況,其中兩個要點:irradiance表達和denoise後面單獨章節來說。

acceleration structure管理

在nvidia目前的turing架構下,是要建立bvh((bounding volume hierarchy))作為acceleration structure。

compute shader有的特性,在bvh建構的時候都有,比如async compute。

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

這裡有top level acceleration structure和bottom level acceleration structure。

各自更新原理比較簡單,地鐵裡也介紹了些技巧,不贅述。

raytracing階段

1,pre trace,

這裡先通過一些更便宜的計算,盡量規避掉比較費的raytracing,比如raymarch地形的depth等等

這部分raymarch會和bvh建構一起通過async compute同時做,

  • bvh建構是一個compute shader的工作
  • async compute會讓raymarch的部分幾乎免費

    2,ray trace

    RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率
    pre trace中沒有intersection的地方,在螢幕空間,每個像素,按照brdf的分布來做raytrace,結果保留distance+albedo;

3,ao

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

有了distance,RTAO就很自然了,做AO+filtering

4,gi

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

以trace的結果做lighting計算,能用上的優化都用上,比如重用deferred lighting已經計算好的部分,用atmosphere中計算好的部分;

已經計算好的部分(也就是frustum之外的)就再做次計算。

這裡真正麻煩的部分是denoise,可以看到做了兩遍denoise。

irradiance storage

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

在lighting階段,會計算raytrace到的hit點的光照,這個光照如前所述,可以預計算,可以重用deferred lighting,可以重新計算。

結果是一個hdr的rgb的值,metro在encoding的時候是轉到ycocg空間,然後y分量用L1的spherical harmonics來表達,cocg還是标量。

分離cocg這裡還是人眼對顔色不敏感,而對于亮度敏感所緻。

然後後續的所有denoise和accumulate都是在這個空間裡做的。

一共耗費96bit。

其他情況,壓到ldr空間等等,在一些極限情況,會損失效果,對于大範圍denoise結果不好。

這裡metro隻是泛泛而談,實際做的話,可以實際嘗試下,拿到切實的原因。

然後trace的結果用sh存的,也是一個低精度的cubemap,是以用來做非常glossy的reflection也是可以的。

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率
RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

denoise

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

raytracing通過硬體能做到相當的實時,但是還遠不到可以計算足夠的ray的情況。

是以我們隻能用少量的ray來模拟近似,也就是用stochastic(随機)的方式,然後通過denoise來恢複畫面。

這裡denoise總體上兩個方向:convolution based(卷積)和deep learning based。

目前相對成熟的是convolution based,比較期待deep learning方向的發展。

metro也提到denoise是最繁瑣的階段,nvidia在gdc2020上的talk也建議大家把denoise盡量早的開始(确實很難也很煩)。

denoise部分主要考慮兩個因素:

  • spatial:什麼空間,什麼數量,kernal如何分布
  • temperal

spatial

1,screen space or world space

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

使用world space更加正确;

2,uniform or not

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

metro用的quadratic kernel來做。

3,權重使用normal base還是plane base

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

權重是基于geometry表面的tangent plane來,可以讓結果更加穩定,而不是基于normalmap的結果。

4,半徑和sample數量的adaptive選擇

這裡就是盡量減少sample的數量,實際情況會根據,距離,方差和ao來選擇;

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

距離不解釋了。

ao就是這裡會比較暗,是以少sample一些ok。

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

(可以看到方差不同的地方,sample數量有所不同)

variance就是變化比較小的地方,就blur的少一些,sample點也少一些。

當幀的sample點方差都是比較大的,随着temperal的積累,方差會逐漸降低。

temperal

temperal這裡就是用了積累多幀的情況,類似taa方面。

這裡metro主要做了兩件事情:

  • temperal accumulation先于denoise
  • temperalAccumulation+Denoies的pass做兩遍

    這兩件事情在是整篇talk的highlight,是有很見解的部分,看的爽!

temporal->denoise

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

這裡列了下temporal->denoise和denoise->temporal兩種方式下各自優劣勢。

實際做的時候,ghosting一直也是非常讓人頭疼的地方。

這裡是我們自己在做開發時候遇到的,就是denoise的時候會做blur,把周圍的像素blur過來,這時候遇到動态物體的部分,就會出現ghost,然後通過temporal accumulation蔓延出去,變成ghost。

multi denoise pass

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

metro這個部分包括兩點:

  • 分兩個pass來做,第一個pass是blur範圍比較大,6m;第二個pass是blur範圍比較小3m,并且加上normal資訊
  • 每個temporal pass是用自己這個pass之前的結果(feedback),不是用下一個pass的上一幀的結果

運作效率

RayTracingInAction[2/3]--地鐵中的光追GI(gdc19)用RayTracing做了什麼pipelineirradiance storagedenoise運作效率

總體還是可以的。

繼續閱讀