《荒野大鏢客2》的大氣雲霧技術

遊資網發表於2020-03-26
作者:安柏霖 騰訊互動娛樂 工程師

《荒野大鏢客2》的大氣雲霧技術

技術一直行業領先,但是一直低調的Rockstar,終於在SIGGRAPH 2019放了大,做了《荒野大鏢客2》(大表哥2,Red Dead: Redemption II)中的大氣雲霧技術分享。

看得也是近幾年最過癮的一篇了,high點:

  • 是發售遊戲中實際使用的、完整的、系統化的技術合集
  • 代表當前最強的大氣系統
  • 技術探索&整合nice,積累深厚,運用純熟
  • 理論、實際開發已經效能優化有很好的平衡,堪稱R&D的典範


motivation & overview

這也是很多優秀工作室做事的一個方法,在處理開創性事情的時候,就會列出一些依據來進行“合理突破”。

這裡筆者也是深有共鳴,是一個很有章法的做事方式。

Rockstar這裡就包括:

《荒野大鏢客2》的大氣雲霧技術

  • 在《荒野大鏢客1》中已經有了不錯的大氣系統,而且這個確實很重要,當然要在2中進一步發展。
  • 受到一些名畫的啟發,筆者也是在看一些繪畫,去一些景色壯觀的地方都會帶來很強的創作衝動(雖然我是寫程式)。
  • 以及基礎的atmosphere scattering系統中,現在確實還有很多可以完善的地方。


通篇是分成data model、render、scene integration三個部分。

data model


《荒野大鏢客2》的大氣雲霧技術

這部分是一個知難行易的模組,所以直接列下特性和做法。

  • 雲的分佈


這塊比較類似Horizon Zero Dawn的做法:

https://blog.csdn.net/toughbro/article/details/48844649

《荒野大鏢客2》的大氣雲霧技術

使用分佈圖來定義雲的整體分佈:

《荒野大鏢客2》的大氣雲霧技術
[ 出來效果這樣的,同時可以有多層的雲 ]

  • 霧的分佈


類似雲的分佈,霧也是有一個分佈:

《荒野大鏢客2》的大氣雲霧技術
[ 沒有fog map的版本 ]

《荒野大鏢客2》的大氣雲霧技術
[ 有fogmap的版本 ]

  • 雲的形狀定義


這塊參考的15年的Horizon Zero Dawn的做法:

https://blog.csdn.net/toughbro/article/details/48844649

基本原理差不多,有一些自己的特色:

《荒野大鏢客2》的大氣雲霧技術

這裡定義雲的形狀:

  • 1個lut定義雲的厚度
  • 1x3d noise,2x2d displacement


效果目測要比Horizon Zero Dawn的好一些。

render

接下來我們看第二部分,這部分主要談渲染部分,包括scattering和lighting的render,相對內容也多一些。

可以說這部分是本篇重點所在。

《荒野大鏢客2》的大氣雲霧技術

  • voxel+raymarching


《荒野大鏢客2》的大氣雲霧技術

處理大氣效果時候,為了兼顧近處的精度和場景的巨集大,使用了混合方案:

  • 近處使用voxelization的方式,得到高精度的渲染結果,reference了刺客信條的一個文章:


https://blog.csdn.net/toughbro/article/details/46706837

  • 遠處使用rayMarching的方式,平衡效果和效率


光照模型


《荒野大鏢客2》的大氣雲霧技術

這裡最終的光照模型,使用這樣的公式列出來,這個比較像大家所熟悉的PhysicallyBasedLighting中的macrofacet公式的模樣,其中三項如下:

  • P:phase的縮寫,是光通過media時候的scattering的情況
  • V:visibility,我們可以近似理解成shadow類的東西
  • L:lighting,也就是光源,直接光,ambient lighting等等


  • phase項

《荒野大鏢客2》的大氣雲霧技術



這裡分成兩個層級:

1、基礎phase模型,是基於Henyey-Greenstein phase function(簡稱HG),這個模型對於single forward scattering處理的比較好。

2、多種scattering組合,基於上面的擅長處理single forward scattering的HG(heney-greenstein)模型。

3、==使用多級HG模型來模擬multi scattering

4、==使用一個clamp操作來模擬back scattering

這裡稍微貼下HG模型的樣子:

《荒野大鏢客2》的大氣雲霧技術

這裡g項是[-1,1]之間,代表從back scattering到forward scattering的情況,表示media的屬性。

theta就是各個角度,phase function就是關於角度的函式麼。

HG函式這部分還是比較物理的,但是multi scattering部分就是比較變通了,是多級HG來模擬multi scattering,各級之間的權重由美術定義。

然後給定g,關於theta就可以預計算出來,放到LUT(look up tabble)貼圖中:

《荒野大鏢客2》的大氣雲霧技術

最後放在一起的效果:

只有1級HG function的時候:

《荒野大鏢客2》的大氣雲霧技術

2級HG function模擬multi scattering+back scattering:

《荒野大鏢客2》的大氣雲霧技術

  • “physically based"的度和變通


這裡也是涉及到一個“physically based"的程度問題,原則上我們是要physically based這樣會盡可能的物理化,好處現在PBR已經論證的非常好了。

但是實際開發中,我們會遇到各種需要折中的地方,或許是物理模型不夠好,或許計算過重等等。

這時候,none-physically-based就還是需要了,這時候建議是,儘可能在高層去做hack和變通,保持底層原子項部分的“physically based"正如phase function這裡,底層是HG function,高層是美術來指定的函式。

  • visibility項

《荒野大鏢客2》的大氣雲霧技術



這一項就是光照資訊中間被遮擋的情況,和直接光照有點不一樣的是,由於這個是一個scattering的過程,所以完整來講是光線一路射過來中間每一步的visibility情況的疊加。

《荒野大鏢客2》的大氣雲霧技術

落實到實際計算中,就是ray marching中間每一步的visibility情況的疊加。

這裡visibility主要針對影響大的兩個case:terrain、cloud來做計算。

terrain使用raymarching的方式構建一個shadowmap資訊;

cloud使用exponential shadow map的方式,來encode shadow map資訊,來達到非常軟陰影的資訊,一共存了6mips(esm的使用在刺客信條的文章裡也有)。

  • lighting項


《荒野大鏢客2》的大氣雲霧技術

ambient lighting部分:

  • 遠處的ray marching部分,就是sky ambient,把sky scattering存到低精度的paraboloid貼圖裡面
  • 近處的frustum voxelization部分,sky light+light probe lighting*AO


《荒野大鏢客2》的大氣雲霧技術

local light 部分,直接就讀light cluster volume。

《荒野大鏢客2》的大氣雲霧技術

  • froxel


froxel也是技術創造的名詞:這個的縮寫frustum voxel;

《荒野大鏢客2》的大氣雲霧技術

也是用voxel的形式,儲存低精度的場景volume資訊,然後用於低頻資訊渲染,比如scattering;

《荒野大鏢客2》中的存了三種資訊:

  • shadow
  • material
  • lighting (結合前兩者來計算)


《荒野大鏢客2》的大氣雲霧技術

shadow volume,注意這個不是陰影演算法的shadow volume,就是存放shadow的volume資訊,包括了普通shadow和cloud shadow;

中間使用了temperal filtering來處理穩定的問題;

《荒野大鏢客2》的大氣雲霧技術

material volume,各種材質資訊,也帶上了wind互動等等(讓我想起了戰神的風力存在volume中)。

也有temperal filter。

  • ray marching


《荒野大鏢客2》的大氣雲霧技術

可能有的讀者對ray marching還不是特別熟悉,ray marching特別常用於volume類的渲染中,鑑於一些計算硬體和資料的限制,有些情況難以很容易的使用ray trace的方式尋找交點,比如local reflection中要對depth buffer找交點。那麼就用步進的方式來找交點,這種方法就是ray marching;這裡的步長的選擇是應用ray marching的時候需要具體斟酌的地方。

《荒野大鏢客2》的大氣雲霧技術

回到《荒野大鏢客2》,ray marching的步長策略選擇也是頗費心思:

  • 考慮到場景深度、ground plane、cloud dome
  • 另外要仔細考慮到雲層的厚度資訊


即便這樣也很容易跳過比較薄的雲層。

  • ray marching優化


先看下最終的效能

《荒野大鏢客2》的大氣雲霧技術

可以看到ray march是佔據著效能的大頭,而且這還是經過優化過之後的結果。

這裡優化就基於兩個大的策略:low resolution + temperal,也就是在低解析度上做raymarch計算,然後通過多幀來重建。

這個部分很精彩,我們多展開。

《荒野大鏢客2》的大氣雲霧技術

這裡raymarch的起點是在froxel的末端,帶上blue noise(可以理解成一個頻率較高的noise了,感興趣可查下)做偏移。

半解析度大小,然後分4幀來計算。

  • raymarch reconstruct


《荒野大鏢客2》的大氣雲霧技術

由於是分4幀來構建,所以每幀只能raymarch 2x2 畫素中的一個,另外三個就要從history buffer中拿。

這裡用了temperal相關的很多做法,一些在taa中頗為常見。

1、使用了3x3畫素color aabb clamp的方式

2、大的深度斷裂的地方,臨接畫素就不考慮了

3、在深度斷裂(depth discrepancies)的地方,放更多的ray

這裡能正確的判定出來depth discrepancy還是比較棘手的,要做的事情就是在6x6(2x2 ray, 3x3 neighbouhood, 所以一共6x6)畫素中,正確的識別depth的min/max;

嘗試1,uniform分佈

《荒野大鏢客2》的大氣雲霧技術

可以看到在frame2裡面,min/max就錯了,這個會導致誤判。

嘗試2,checkerboard方式

能處理的case好很多:

《荒野大鏢客2》的大氣雲霧技術

但是這種情況下還是不行:

《荒野大鏢客2》的大氣雲霧技術

總之區域性的分佈策略總是有cover不住的情況了,還是要引入整體的資訊才行。

嘗試3:checker board+depth neighborhood analysis

先是拿到3x3tile(每個tile是2x2畫素)的depth min/max,然後每一個tile中和其餘的8個點比,如果其餘的8個都是min,那麼這個就取一個max depth的點。

  • up scaling

《荒野大鏢客2》的大氣雲霧技術


《荒野大鏢客2》的大氣雲霧技術



up scale這裡是4taps dither,depth連續就平均,不連續就取最近

  • 效率


《荒野大鏢客2》的大氣雲霧技術

長的raymarch部分是最消耗的。

《荒野大鏢客2》的大氣雲霧技術

scene integration

第三部分,integration,也就是把計算好的光照等和場景整合起來。

《荒野大鏢客2》的大氣雲霧技術

這裡是一個integration完整的示意圖,我們接下來可以一步步看看。

sky scattering

sky scattering演算法上是Precomputed Atmospheric Scattering,三個特點:

  • 考慮了earth shadow
  • 分幀實時更新的
  • 存放在32x16x32的LUT中


《荒野大鏢客2》的大氣雲霧技術
[ 用於sample sky scatter的深度資訊 ]

在sample sky scattering資訊的時候,就不是raymarch每一步都踩了,否則雖然更加正確,但是太費了。

最終按照depth資訊,就依據depth來sample一次。

《荒野大鏢客2》的大氣雲霧技術
[ visibility資訊 ]

然後visibility資訊(類似shadow)資訊都是分離的。

放在一起的效果:

《荒野大鏢客2》的大氣雲霧技術

  • 光照組成


把前面列的放在這裡:

  • frustum volume lookup
  • ray march result
  • sky scattering / transmittance


  • sky irradiance probe


《荒野大鏢客2》的大氣雲霧技術

地圖裡32x32的3rd order spherical harmonics probe map, 每個probe覆蓋(256mx256m),這個用作sky irraidance probe。

總結

ppt本身的總結是有這麼幾條:

  • volumetric效果是“一等公民”
  • 這是一個統一,基於物理,支援多種材質的scattering/transimitance系統
  • 近處是frustum align的volume based技術
  • 遠處是raymarch based的技術


個人的閱讀總結:除了第一篇的high點之外,有幾點印象非常深刻

  • 對大量的渲染技術運用的如此純熟靈活,非常給力
  • 能夠hold住如此複雜的系統,非常給力


研發的本原的樣子

一系列的筆記,可能是解讀技術文章以來最多的一次了,筆記部分基本上是大家看了原文之後大致能記住的部分,實際上原文涵蓋的內容要更多更雜,然後這背後還有更多的探索和嘗試,因為篇幅的原因沒有寫出來。

讀的時候完全沒法像一些論文,尤其是少專案而重理論和demo向的,可以簡單的做抽象和總結,可以“一句話說清楚”。

實際像《荒野大鏢客2》這樣的專案,這個就是研發中所面臨的問題,理論摻雜著妥協與變通(hack),並且要覆蓋極高的複雜度。

實際做的時候,巨集觀的視野?是的;紮實的理論?是的;紮實的engineering?是的;充分的耐心?是的;靈活的變通?是的;

像我個人之前做《天涯明月刀》《無限法則》相關的技術分享,ppt寫的時候往往寫得“重點突出”、“易聽易懂”甚至還帶著兩個笑話;

而實際上,做專案開發中,就是一個複雜度高的多,繁雜的多的過程,但是那麼來寫ppt,往往觀眾會聽得雲裡霧裡,所以最終的結果還是“一句話說清楚”。

《荒野大鏢客2》,分享者也足夠耐心,列了方方面面,包括raymarching中優化的幾個失敗案例,確實更像研發原本的樣子。


來源:騰訊遊戲學院
原地址:https://mp.weixin.qq.com/s/a762JlqC3EszLHbylsfhIw

相關文章