SIGGRAPH 粗讀丨看看《地平線:西域禁地》燃燒海岸DLC中的雲層渲染(下)


3樓貓 發佈時間:2025-01-04 15:33:21 作者:Hakumen Language

前言

之前的中篇中,我們粗讀並分析了作者集中講述並較為關鍵的三個部分:(數學與製成)
建模密度採樣光照計算
相對於之前舊方案中的2.5D體積雲,作者集中介紹了為使飛入雲層成為可能而改進的體素雲系統的取捨與優化。其中存儲空間指令調用(或算法複雜度)的平衡是作者最核心的一項實踐智慧。
如果只是純理論研究,那可能瞭解到光照這一步也足夠了。這次的下篇剩餘的部分可以看作是工業化方面的一些收尾,以及整合與總結。
文章還是以翻譯原文的講稿為主。這次分為了上中下三篇——這是其中的下篇;打星號的部分則是我個人的補充說明。整篇分享中視頻非常多,很多動態效果是完全無法用文字描述的;一方面我也轉錄了很多GIF段,另外原始精度的視頻可以從文末鏈接去源地址下載。

1 光線步進追蹤——Ray-Marching

徑直向前,我們也需要關注光線步進(ray-march)方面的性能節省,以支撐飛躍雲層的性能需要。
*Marching right along翻譯過來就是徑直向前,作者這裡又雙押了march這個雙關語。
回顧一下我們的困境(dilemma)——由於沒有很好的方法能獲知雲層(體素範圍)中每個採樣點的相關位置,我們無法高效地沿射線進行採樣。
之前的封包法(Envelope method)雲層方案中,我們整合了距離步進映射(distance step mapping)和錐體步進映射(cone step mapping)兩種方式,來改進我們從2D數據生成的體積雲中進行採樣位置選取的過程。(*上篇中介紹了)
現在我們面臨的是真正3維的問題了(基於體素)——幸運的是,有一項我們準備許久的技術此時可以派上用場了。
Sphere tracing is a technique that uses the 3-dimensional distance to the closest implicit surface to determine step size. A signed distance field stores measurements of these distances for every point in space. Positive values are outside of the object and negative values are inside.
球體追蹤(Sphere tracing)是一項使用三維距離來確定最近的特定表面的技術(以確定步進長度);而一個有向距離場(Signed Distance Fields,縮寫為SDF)存儲了空間中每一點的最小追蹤距離——正值表示在物體(雲)外,而負值表示在物體內。
當沿著體積雲層進行ray-marching時,就可以使用(射線上某一點)在距離場中的距離值來作為最大的步長,以減少射線上(無效)採樣的數量。
有兩篇很好的介紹SDF使用的資料:
  • 第一篇是Inigo Quilez的網頁,你可以瞭解如何為一些原始(primitive)形體計算距離場。
  • 第二篇是GDC上Sebastien Antolnen的講座,從中你可以瞭解如何在高性能要求的場合高效使用這項技術。
*不僅限於雲層這個案例,在能使用SDF的場合,往往都會用來作為ray-march的重要補充。
*這個案例中,通過任意一點座標查找體積雲SDF,得出的值就是“從這一點為圓心剛好與雲體相交的最小半徑”;雖然查找無關方向,但是這個預計算的值是準確的,可以作為下一次遞進的步長。
當藝術家完成構建他們的“人造雲層形體”時(之前一篇介紹了,是用了生造詞frankencloudscapes):
我們生成了一個3D的SDF,並把它寫入了一個單獨的NVDF(*NVDF是之前介紹的一種體素雲數據結構的縮寫)。數據的原始範圍是從-256到4096(米),但我們將其縮放至一個0到1的範圍內。在圖中(中間一張)你可以看到在遠離雲的位置,值逐漸增加(越來越白)。
我們將其與雲模型數據的NVDF分離開,因為它們會被頻繁(每一步進過程)進行查找,因此我們不希望無緣由地引入內存瓶頸。提到內存瓶頸,距離場數據的壓縮方式也很重要。
這裡展示了Nathan Reed整理的(*原文還用了world-famous一詞)BC格式表,以解釋這一問題:
由於SDF會被頻繁採樣,因此對它壓縮能降低每個紋素需要的字節數,以減少內存帶寬佔用——最終提升性能。
一個1通道的BC4似乎就很理想。而其中的tradeoff是,更少的字節數意味著較低的精度,而這對於一個基於SDF的yaymarch來說是一個大問題。
如果解壓縮值過低,則會導致需要消耗額外的raymarch步數;如果過高,則會導致渲染故障。(*這裡對應起來不太直觀,但原文確實是decompressed value)
如何解決這一問題?我們採用了被稱為“渲染工程師的黑魔法”的方案。(*原文就是Rendering engineer black magic,之前一篇也說了,作者喜歡使用一些技術分享中不常用的詞彙)
通過使用高級技術工程師Hugh Malan開發的一套定製化BC1壓縮器,SDF能在被壓縮後依然能得到接近16bit的精度。(*1byte=8bits)
There is a bonus slide right after this one with an in-depth explanation of Hugh’s work that you can look at, but to sum it up, we split up the data into three channels and then reassemble them after we sample the SDF in the ray-march shader. This approach worked because SDF data is smooth.
這裡(*原文的bonus頁)中提供了對這套方案的詳細解釋,不過總的來說,我們是將數據分別存入三個通道中,之後在ray-march shader採樣SDF的過程中重新集成——這個方式之所以能生效,是因為SDF數據是平滑的。
最終對於不同的射線長度,這(相對於無壓縮的紋理數據)大約減少了10-30%的內存瓶頸——應對於我們最頻繁採樣的體素數據。
由於這是我們的體素方法中的最後一部分NVDF數據,至此我們可以整體對照一下單個系統的內存開銷:
  • 垂直輪廓法VP, 大約0.5Mb
  • 封包法EVM,大約9Mb
  • 體素方法VM,25Mb
因此你可以看到額外的細節是從哪裡來的——沒有什麼是能憑空出現的(Nothing comes for free),但有了體素雲我們就能實現很多其它方法無法達到的效果。
不過這也不是我們唯一的加速體素ray-march的方法。
首先,我們定義了射線的邊界,以限制潛在的採樣數量。
射線從攝像機發出,以體素柵格邊界作為終點——或是命中範圍內的幾何體。
下一步,我們需要計算下一步採樣位置的步長。這個距離的計算是基於三個來源:
  • 基於距離場的有向距離值。
  • 在雲體積內自適應隨距離逐漸遞增的步長值。
  • 以及一個分時抖動的偏移值(temporally jittered offset)以消除降採樣帶來的噪聲。
其中SDF被用來在雲層外的位置以最佳方式放置採樣點。(*圖中空心圓的部分)
自適應步長是基於到攝像機的距離來在雲體積中放置採樣點。這樣,距離攝像機越遠的雲就能使用盡量大的步長,不同距離的雲採樣都能以相對最佳的步長進行。
而抖動偏移值從近處的動態到遠處的靜態雲層之間進行切換,以降低採樣精度不足帶來的視覺故障,同時也避免使遠處雲層閃爍(shimmer)。(*這裡應該是說不同距離有不同抖動偏移值)
有向距離值(步長)以自適應步長作為最大值,因而當在雲層內採樣(有向距離值變為負值)時,我們切換到使用自適應步長值。
步長值之後會被累加到採樣距離上,以推算下一步的採樣位置。
當要進行採樣時,我們也查找SDF來進行一項優化。
如果SDF的值大於0,意味著採樣點在雲體積外,因此不需要進行採樣操作。
如果值小於0,則按之前(*前一篇)描述的收集密度和光照樣本,最終延射線方向累加。
之前的部分中已經數次涉及到特定場合的性能表現,而現在是時候系統性地看看性能情況了。重要的是對不同情況下可見物體的數量有一個基本的把握:
  • 當飛躍雲層時,雲是視覺中主要被渲染的物體。
  • 當從地面遠距離觀看時,雲的開銷應按比例縮小以讓位於其它的物體。
  • 動態平衡這項開銷是衡量我們的雲系統是否成功的關鍵。
因此,讓我們看看不同情況下的渲染數據:第一種是從地面觀看雲層時,需要混合地面和雲層;第二種是全屏雲層。每個案例都以960x540分辨率渲染。
從地面開始,在沒有光照或ray-march優化時,開銷是10毫秒。
通過基於體素的光照優化(*之前介紹過,經過解耦預運算),降低到6.1毫秒。
經過ray-march優化,降低到2.2毫秒。
加上其它幾何體(geometry)pass的開銷,總開銷是9.2毫秒。
當我們來到空中,在雲層和可見的遠景之中。在沒有光照或ray-march優化時,開銷是12毫秒——這種增量主要來自更多沿著俯瞰的方向穿過雲層的射線,這部分開銷可以通過對雲的高度做偏移量(來減少射線的長度)以進行緩解。
通過基於體素的光照優化,降低到8.2毫秒。
經過ray-march優化,降低到4毫秒。
從圖中可以看出,幾何體pass的開銷降低了2毫秒,而云渲染的開銷增加了2毫秒——仍然是比較平衡的。
當來到全是雲層的高空,原始無優化的開銷是10毫秒。
通過基於體素的光照優化,降低到8毫秒。
經過ray-march優化,降低到4毫秒。
幾何體pass的開銷降低了1毫秒,而云渲染的開銷和之前一致。
因而在不同的情況中,性能預算被從地面幾何體很好地傳遞(handoff)給了體積雲。
總結一下:
  • 我們使用了壓縮的SDF來規避內存瓶頸,並用來優化射線採樣的步長。
  • 我們(在逐步採樣的過程)組合了SDF、自適應步長和抖動採樣的方式,以獲得在降採樣精度情況下最佳的降噪效果。
  • 體積雲的整體開銷在2.2毫秒到4毫秒之間,取決於觀看的位置在地面還是空中。
  • 性能開銷從地面到空中有合適的規模適應(scales properly)。

2 渲染——Rendering

*這裡的rendering主要概括了前述方案整合後的高幀數模式的策略。
30hz、60hz、40hz或其它——每個人都有自己傾向選擇的遊玩幀數(*刷新率,雖然不完全一樣)。我們作為圖形程序員和藝術家的工作是確保各種渲染模式都是受支持的。在基礎性能表現的幀率勉強達到(squeaks)30hz模式的標準時,我們還需要支持高幀率模式——意味著每幀只有一半的渲染時間預算。
*其實誰都想畫面又好幀數又好,但實際上不可能兼得。這裡作者團隊的思路是先按高畫質30幀來做。
Recall that for the Envelope Method, we did away with temporal upscaling and split the render into two passes: High res in the distance to prevent aliasing and low res up close to improve performance for the most expensive parts of the ray-march. Would a similar approach work for 40 and 60hz modes? The answer is yes. For High framerate modes, we do this exactly the same way.
回顧在封包法中的超精度策略,我們執行了一項分時超精度(temporal upscaling)算法,並將渲染步驟拆分成兩個pass——遠距離的高精度pass,以避免走樣;近距離的低精度pass,以提升開銷最大的ray-march部分的性能。類似的做法是否能用於40和60hz的模式呢?答案是肯定的。對於更高幀率的模式,我們採用了完全相同的策略。
這裡展示了一個例子:
雲層在30hz模式下的幀開銷是4毫秒。當我們將渲染拆分到不同分辨率的兩個pass中,開銷降低到2.1毫秒——這個方案被用於40和60hz模式中。
讓我們將兩種模式並排做一個對比。
可以看到在60hz的視頻中,在有銳利和緻密特性的雲層處,畫面會顯得更“像素化”(pixelation ),但低密度的區域能較好掩蓋這一點。除此之外結果已經足夠好了,因為這種體驗本身幾乎沒有損失。
*有興趣的可以去看看1080P版本的原始PPT,壓縮後的圖片和GIF已經無法反映這種區別了。
小結一下:
  • 我們把雲的渲染拆分成了兩個pass,近處低精度、遠處高精度。
  • 這幾乎使渲染時間減半了——而這能很好符合60hz模式的渲染時間需求。
  • 40hz模式也使用同樣的方法。
*雖然都知道將分辨率會提高精度,但作者的這種組合策略確實非常符合雲的視覺特點及需求——近處相對模糊而遠處清晰。

3 製作過程——Production

*到了這一步才算進入很多人喜歡提的一個詞,“工業化”製作。第三代體積雲系統正式作為一個可以豐富參數化的可交付模塊提供使用了。
下面讓我們看看這個系統在遊戲中的一些實際應用。分別從為背景元素和可探索元素構建雲的形體開始。
This is a “chickenscratch” doodle that I made of post apocalyptic Los Angeles. It helped to lay this out along the east-west and North-South views because these are the directions against which we need a good composition of silhouettes in terms of the arc of the sun.
這裡通過潦草的手繪草稿(“chickenscratch” doodle)展示了洛杉磯的後啟示錄概念圖。這有助於我們基於“從東到西”和“從北到南”的視圖來安排景物的排列,因為在這些方向上我們需要安排一組好的物體剪影組合——對應各方向的太陽弧度。
我們從放置大規模的雲層開始,因此它能在一天的各時段、從各角度觀察都有不錯的效果。
下一步,我們添加其它的特性和相鄰雲層結構。(*原文是connective tissue)
對於一部分雲我們用Atlas工具添加通道和孔洞,以增加探索體驗。
在製作時我們也會試飛一下以快速度體驗天空雲層中的實際情況。
從雲層孔洞中穿過自身就足夠有趣,以至於有時很難把工作和玩區分開。
*so it was hard to distinguish work from play at times——開發中的內容往往會重複很多次而讓人疲倦,儘管如此還能覺得有趣,這是開發遊戲中難得的體驗。
讓我們看看普通速度飛躍通道的視頻(*雖然GIF還是加速過)。
注意光照質量在雲的內部以及通道的背面的效果——光照運轉良好。
能看到翅膀尖端的細小氣流麼?這是通過檢測翅膀與雲交疊時發射粒子來實現的。
以防萬一你會覺得“雲層不會有這樣的通道”,這裡是一張我拍攝的照片——右邊的黑點是一隻鳥,而不是一個機器恐龍。
我們對每塊雲都多次執行這一步驟,之後將它們組成一組雲的形體。
這裡展示了實際遊戲中不同位置觀察到的雲形體。
對於轉場動畫我們可以使用一個變換(transform)來移動已有的雲層,避免增加額外的內存。
*這裡是說運行時把已有的體積雲移動入畫,就不用額外生成動畫用的體積雲了。
對於遊戲最後的BOSS戰,我們構建了環繞的雲形體,使場地像一個競技場。
總結一下:
  • 以體素雲方式建模比舊的“人造雲層”方案更簡單。
  • 這是工作流程上實在的範式轉換(Paradigm shift),因為你可以製作任何形體的雲——甚至是在天空寫字。
  • 轉場動畫能使用已有的雲形體,通過空間變換(移動雲)來節省內存。
  • 也為例如BOSS戰等場合訂製了專門的雲形體。

4 雷鳥降臨——The Stormbird Encounter

被我們稱為“體素雲方法”的體積雲系統從結果來看運作良好——可以看到和之前的方案比較來說,體素雲實現了各種突破。
演進(Evolution,可以理解成動態流動)是未來待開發的一項內容。但要實現這一點就不僅需要解決實時體素雲的演進,還需要生成實時變化的SDF了——這就留給未來繼續開發吧。
我們把這項成果視為完全的成功——因為我們不僅很罕見地保留了初期預想的所有內容,並且創造了更多。
一項有價值的takeaway是:雲的密度不僅僅是關於體素的密度,也關於結果的視覺感知複雜度。採用高精度當然是其中一項方案,但在計算機圖形領域往往有不止一種問題解法——如我們所介紹的那樣。
在結束講座前,我還有一項內容想分享。遊戲中,我們想提供不僅僅是飛躍雲層,而是額外創造在一片風暴雲中的一段獨特的遊戲體驗。
遊戲中的雷鳥有著很多背景設定(lore)。這是一隻天空中的頂級捕食者(apex predator),可以控制小範圍的天氣,以閃電製造風暴雲。為什麼之前我們一直沒在遊戲中展示這一點?很簡單,因為之前的技術方案不支持,直到現在(*體素雲)。
主世界設計師Elijah Houck構想了很多追擊玩法(cat and mouse game)的方案。它是一個頂級捕食者,而你的坐騎相對顯得很小。Elijah想象它把玩家引入它的巢穴——一個風暴雲中,之後突襲並擊殺了你的坐騎,好在玩家角色——alloy有滑翔器。
這裡展示了這段追擊戰,在最後擊殺它後風暴雲也消散了。
*這裡原PPT有一段一分半的演示,這裡沒法放進來了——效果很不錯。
因此,留給我的任務是設計雲的外輪廓、完成光照方案、設計雲的內部通道——以及最重要的是讓它看起來不像一個簡單的雲孔洞。最後,在擊殺雷鳥後要讓雲層消散。
我們希望它呈現為一個很局部的風暴,而不是類似西之禁地中的超大型風暴。
這裡展示了一個早期的流體模擬嘗試——一縷垂直擴散的雲,底部有著纖細材質的邊沿。
這裡展示了添加了(來自西之禁地中的)輝光代碼後的效果——這一早期結果在兩個角度上改變了風暴雲的開發思路。
首先,我們認識到這相較於我們想構建的遭遇雷鳥的雲(需要有足夠的內部結構)來說太小了。
其次,注意到底部的輝光效果在視覺上的開口效果。這使我們考慮使用內部光照來突出展示開口。
因此我確定無論地面上是否有放電現象,雲的內部需要被照亮來突出某些內部結構。我也試著添加了一些預製好的閃電效果。
在風暴雲範圍下方,我們也使用了局部天氣系統(來製造降雨)。
這裡是遊戲中整個雷雲外部的遠距離完整展現。
在雲的內部,我希望玩家遭遇一些預期外的內容,不止是建模好的孔洞——而是一些對人類來說很詭異而對雷鳥來說很舒適的事物。玩家遭遇它時,會覺得既可怕又合理。
合理的一種考慮是雲層中可能有一個能量中心,使雷鳥能維持這種非自然的風暴。當擊殺雷鳥後,能量中心和雲都消散了。
圖中展示了被我暱稱為“the Egg”的這一能量中心。其中小型的電弧顯然受到了Nikola Tesla的啟發。
我們也持續調整了很多版,直到“egg”的下方能明顯看到放電現象——這讓它起到了一個視覺突出的作用。
作為實現的概括,這是另一處我們取自超級風暴系統並與體素雲結合的光照技術。
對於內部空間,我使用了Atlas工具來切開孔洞和創建egg區域。我確保在此過程增加了足夠的小開口(pockets),使雷鳥能隱藏在其中並發動突襲。
我也添加了足夠空間的大開口,使光線能進入雲內部,使其在一天不同時段呈現不同效果——畢竟這是一個開放世界遊戲。
基於所有這些已經實現的細節,Elijah製作了遭遇戰的音頻,提供了一些很棒的音效。
因為我們升級到了新的體素雲渲染方案,並且開始探索雲的物理特性以及環境交互,以及所有這些特性都開放給遊戲腳本來調度——我們最終能為開發組提供更多,併為玩家呈現獨一無二的雲層飛躍體驗。讓人興奮的是,這僅是這類遊玩體驗的開端。
因此最後我們把圖表添加了兩行——現在只有體素雲系統能用於任務設計以及有著更多潛在的擴展可能性。
*這個雷鳥的案例就是一個既有壓力但又良性向上的開發環境中,從一個小的原型到交付的功能的方方面面,其中有很多開發者的自主創新和高要求——得益於體積雲系統的“範式轉換”。

結語

作為一款“偏罐頭”的一度獨佔的3A大作的續作的DLC中出現的內容,我對於有多少人能實際玩到這些讓人振奮的體積雲效果感到不樂觀;至於後續移植到PC,這種針對PS5踩在性能及格線上的高質量效果,要適配各種不同組合的PC硬件想來也是讓人頭大的。對於“開放世界”,可能玩家第一時間會想到“罐頭”,而體積雲的製作者想到的是——它在time of day需要有不同的合理表現。
無論如何,至少在PS5這個世代的初期,這些索尼第一方遊戲的整體質量是讓人放心而振奮的——和現在主要第一方遊戲的境遇可以說是天上地下。
雖然我沒有玩過這款遊戲,但在本來就數量不多的高畫質3A遊戲中,這款遊戲裡的體積雲應該是獨一份的了——更何況Nubis3的開發者已經是十年以上的資深體積雲渲染專家了。
一方面,平衡內存和指令調用的實踐智慧讓人印象深刻——即使需要降低分辨率來提高幀數,也不是簡單的整體降低,而是區分了兩個pass;另一方面,作者通過照片和觀察生活中的物理現象的方式來歸納模型——這種以實證為基礎的方法也讓人覺得很靠譜。
參與開發的成員,前置的講座,以及參考文獻

參與開發的成員,前置的講座,以及參考文獻

最後是本文的資料鏈接:
Nubis3: Methods (and madness) to model and render immersive real-time voxel-based cloud 1080P PPTX PDF

© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com