前言
在之前讀過一個介紹體積雲的系列,當時是介紹的《地平線:零之曙光 》中的體積雲方案。當時Guerrilla(遊戲的開發工作室)的方案還是以在地面看天穹的雲層為主要實現目標,在PS4上實現了不錯的效果。
隨著續作及其DLC的陸續發佈,開發組對於體積雲在更多場合呈現更豐富的樣態有了思考與實現。這篇分享的主講人Andrew Schneider本身是一個大氣渲染方面的專家,有著十年以上體積雲渲染的研究與經驗。
文章還是以翻譯原文的講稿為主,並且由於原文的篇幅很多地方較長,會進行適當的精簡和概括。由於圖文內容量都很大,這次會分為上中下三篇,打星號的部分則是我個人的補充說明。
1 前導介紹——A Brief (Nubis-Centric) History of Cloud Rendering
*這部分如標題所述,主要是介紹了作者自己(以在Nubis系統中開發的為主)的體積雲渲染履歷與技術路線——Nubis是他們這套體積雲系統的名稱。
*這一段作者主要回顧了2011年的一篇論文內容,其中介紹了當時用於動畫Rio的離線渲染體積雲技術。這個當時被稱為SmogVox的技術是他的同事Trevor Thomson開發的,由於用到了光線追蹤技術,在離線狀態下渲染1920x1080的分辨率大約需要4-10分鐘一幀。
我(作者)於2014年加入了guerrilla,當時負責改進遊戲《Killzone》中使用的2D天空盒。
一開始,我試圖以移植離線渲染中用過的那套體積算法來解決雲形體的問題。
我構建了一個自定義的流體生成器(fluid solver,直譯是求解器)——暱稱是Aero,使用了在Houdini被稱為micro solvers的子系統。
Micro solver是Houdini計算一幀中的流體模擬的模塊化方案,允許使用者重排、修改、引入新的解,以及進行更多你需要的定製(如圖)。
作為與更流行的燃燒樣式(combustion-style)生成器的對比,Aero是流線式(streamlined)的並在雲體積逐步增大方面進行了強化。(*參考GIF)
回到2014年,我們模擬了幾種不同雲的形體並嘗試了不同的渲染方案,但它們都無法適應PS4的性能需要,因而無法用於當時的遊戲前作《地平線:零之曙光》。
當時時間不足了,因此這項研究工作(流體體積雲)就被擱置了,我們轉而進行開發。
我們開發了多種不同的建模和渲染方式——可以視為是一種2.5D的雲,因為渲染這些雲的數據不是通過3D的體素數據,而是2D紋理數據。我們把這一雲層系統稱為Nubis,下面我們回顧一下這個系統是如何運作的。
*這部分細節其實當時介紹2015年的那篇體積雲實現中比較詳細的介紹了。
*圖中簡要回顧了一下這個系統不斷進行增量開發進化的脈絡,以及相關的分享內容。
What made Nubis successful in our games was the ways in which we compressed our cloudscapes and added density and lighting details, which are specific to clouds, at render time while fine tuning a rendering technique known as volumetric ray-marching. This allowed us to model cloud evolution and time of day cycles which, in addition to producing distant clouds, could produce superstorms with red lighting, and some low altitude fog-like clouds that the player could fly through. Our method of ray-marching turned compressed cloud models into rendered frames of clouds in between 0.2 and 5 milliseconds depending on if we viewed them from afar or we if flew through them.
使我們的Nubis系統得以成功的是,我們壓縮了雲的形狀並添加了密度和光照細節——參數與具體雲的種類相關,並通過微調後的被稱為體積光線步進(ray-marching)的技術進行渲染。
這使得我們能對雲的光照進行建模,並模擬出一天中不同時間的光照效果——除了產生遠距離雲層的視覺外,還能產生有著紅色閃電的風暴,或是部分玩家可以穿過的低海拔霧狀雲層。
我們的ray-marching方法將壓縮的雲模型渲染成體積雲需要0.2到5毫秒,取決於玩家的位置是遠遠地望向雲層還是從中飛過。
讓我們簡單看看這些建模和渲染方法是如何起作用的。
在一個ray-march過程中,一旦確認像素中包含了雲層,就需要執行以下步驟:
- 沿著射線與雲層的頂部和底部相交的部分逐步執行計算。
- 對於每一步(雲層中)的採樣點,採樣密度和光照——這需要第二次的(比較昂貴的)朝向光源的ray-march過程,之後將這些數據累加到前一步的結果數據上,為每個像素計算顏色和透明度數據。
- 重複這一步直到像素變得不透明(full opacity),並且雲體積內的每一個像素都需要執行這一過程。
讓我們看看每一個步驟執行時的具體過程,從ray-march算法的核心——採樣密度開始。
這裡我會集中回顧兩種我們使用過的雲渲染方法,兩者都直接影響了我們體積雲渲染的路徑:
- 第一種被稱為垂直輪廓法(Vertical Profile Method),用於高海拔的對流層的雲(玩家無法抵達的)
- 第二種是封包法(Envelope Method),我們用於玩家可以抵達的山嶽雲層。
兩者有其各自的密度採樣方法,但共享一些類似的設計思路。
那些被我們稱為Nubis數據場(Nubis Data Fields,縮寫NDF)的2D數據場,包含了雲在compute shader中渲染的指令——用於從中“解壓縮”得到3D雲的過程數據。
這些2D數據場覆蓋了我們地圖16km的區域,在渲染時從中採樣以構建3D雲的形體。
兩種方法的ray-march步驟最終都構建了一個高精度的3D體積(如圖)——從一個低精度的空間輪廓(dimensional profile)開始。
雖然可能看起來有些相似,但構建這些空間輪廓的方式實際上(在不同方法中)有所不同。
在垂直輪廓法的例子中,我們從5個2D的NDF開始:
- 雲層的最小、最大高度定義了雲的垂直範圍。
- 頂部類型和底部類型定義了垂直輪廓的兩個查找紋理(lookup textures),兩者相乘就得到了我們稱為垂直輪廓的數據。
- 然後,我們通過覆蓋率數據來縮放這個垂直輪廓,以控制雲形成的位置。
在封包法的例子中,我們從4個2D的NDF開始:
最小、最大高度
定義了封包雲層的渲染範圍。而空間輪廓是三個梯度的乘積:
- 一個指向下方的頂層梯度
- 一個指向上方的底層梯度
- 一個從外向內的邊緣梯度
我們使用了3D噪聲來侵蝕前一步的空間輪廓,並“超精度”至最終看到的結果。
我們研發了被稱為Perlin-Worley噪聲的紋理來模擬纖細的和波浪狀(wispy and billowy)混合的細節,並單獨使用Worley噪聲來模擬波浪狀的細節。
These were combined in various ways per model to create what we called noise composites for potential wispy and billowy details at the sample position.
它們在不同的雲模型中有不同的混合方式,以創造被稱為噪聲組合的效果——用於雲層採樣位置中的(潛在的)纖細和波浪狀細節。
之後我們使用類型數據(Type data)以混合纖細到波浪狀的噪聲。
The erosion was modeled as the subtraction of the inverse of the dimensional profile from the noise composite.
雲的侵蝕效果建模自:噪聲合成減去空間輪廓的反相。
“Pseudomotion” was simulated for both models by animating the noise in the wind direction.
“偽運動”(Pseudomotion)是通過按風的方向執行噪聲動畫來模擬的。
在採樣完密度後,我們採樣光的強度。
兩種方法都依據以下3項來定義光的能量:
- 直接光散射,代表所有從太陽入射的光能量。
- 環境散射,代表從天空和相鄰雲層來的光能量。
- 次級散射,代表從其它來源(例如光照)中來的光能量。
計算這些能量有著不同的方式。完整的講述在2022年的講座中,而現在我會簡要概括一下。
給定採樣點的直接光散射的計算,是通過一個包含3項概率的公式:
- 傳播係數、散射相位以及多重散射(Transmittance, Scattering phase, and multiple scattering)。
- 傳播係數用來度量光學介質中給定深度的光量。圖中展示了隨著雲層中的深度增加,光是如何遞減以及被吸收的。為了收集這一深度,你還需要傳導(conduct)一根(非常昂貴的)光步進射線朝向光源。
- 散射相位用來度量給定採樣位置的能到達人眼的能量——基於給定的視角向量和光照向量。雲中的光線散射是由於其中的微小水滴或冰晶。光線在雲層中的散射有著延路徑增加的趨勢,因而我們使用Henyey Greenstein相位函數來實現這一效果,綜合了藝術家導向和物理現實。
- 多重散射描述了光經過水分子(molecules)多次折射後,散射進入我們的視角向量的光量。我們使用空間輪廓作為概率場的基,以描述你在雲層中時(隨著深度增加)內散射(in-scattering )逐漸變多的趨勢。我們使用另一個beer-lambert衰減曲線來計算光線被吸收導致衰減的程度——這一衰減也考慮了雲層下方會有相對更少的光散射入雲層的事實。
最終,我們縮放這一相位函數來確保它的方向性。
這裡展示了沒有多重散射估算(上圖)和添加了這一估算的不同效果。
為了估算射入雲層的環境光(不使用光線步進),我們再次將這一幾何描述建模成了概率場。
主要的環境光來源自上方和周圍,並滲入(penetrates)雲層表面。
空間輪廓已經提供了雲的從外向內的梯度,我們使用它的反相來創建一個梯度——以描述一個環境光到達雲層內某點並散射進我們眼睛的概率。
這裡展示了一組對比:上方是隻有直接光能量的結果;下方是綜合了直接光和環境光的結果。
最後考慮次級光照能量。通常來說,對於任何放置在雲層內的光源來說,每次採樣都需要昂貴的光線步進計算(向光源)。圖中的例子就需要追蹤3根步進射線——而這不是一個理想方案。
再一次,我們把這建模成概率問題。
我們建模了一個光體積,以估算光源周圍每個採樣位置的光能——在主採樣步進射線(primary ray-march)上進行。其中有更多細節,不過後面我會展開解釋它是如何作用於我們的體積雲。
這裡展示了基於這一計算,遊戲中雲層風暴呈現的效果。(*紅色閃電作為次級光源)
The next step (pun intended) is to determine the step size for our march so that the next sample can be placed along the ray.
下一個步驟是確認射線上採樣的步長。
*這裡的step,作者標註是pun intended——雙關語。有點程序員冷笑話的意思了。
垂直輪廓法採用了一種自適應的步長,它隨著到攝像機的距離逐步增加。這樣越遠處(需要精度越低)的位置採樣數就越少。
圖中的局部天空需要大概半毫秒來渲染,而全屏整體的天空則需要大約2.2毫秒。
然而,為了支持能以飛行的方式穿過封包法渲染的雲層——它們都距離攝像機很近,因而需要很多采樣數,我們不得不發揮一些創造力(get a bit creative)來避免過多的採樣。
我們混合了兩種分別被稱為Cone Step Mapping和Distance Step Mapping(直譯是錐體步進映射和距離步進映射)的方法,以便僅僅依據高度數據就能高效地放置採樣點。
當計算光線步進時,我們基於(前一步的採樣點垂直)和表面的交點生成一些錐體,並計算和這些錐體的交點以確認命中雲層之前的最大可能步長。而距離步進映射被用於確保,不在雲層外的區域消耗太多采樣點。
*這裡原文沒有描述出錐體追蹤是一個迭代的過程,從圖中可以看出,是循環執行步長減半+錐體求交點的過程,直到命中雲體。
當我們開始在封包雲層內部採樣時,我們開始採用小的步長來採樣實際的雲層密度。
圖中你可以看到採樣的位置——以紅色點顯示出來,我們集中採樣雲及其周圍的空間,而在空白處則沒有那麼多的採樣點,顯然這是更好的一種分佈方式。
這種採樣能提升多少性能呢?不進行優化之前,開銷是4.2毫秒。
在優化後的時間是1.3毫秒。
使我們的雲系統進一步提升其性能表現的一個方式是,改進逐像素進行ray march的現狀(使用一定的超採樣)。兩種方式都對雲的渲染有加速作用。
垂直輪廓雲使用了分時超採樣技術,將渲染的開銷分攤到了16幀中。(*原文用了Amortizes ,分期償還一詞)
對於遠處的雲,它能使原本需要20毫秒的渲染效果在一幀內以2毫秒的速度(分幀)完成;但對於近處的雲這種方式是不解決問題的,因為攝像機會快速移動。
因而,對於置身之中的封包雲層,我們採用瞭如下方式:將渲染過程分到兩個pass中,靠近攝像機處使用昂貴但低清晰度的渲染模式,而較遠處我們希望能減少走樣。
至此,我們已經覆蓋了之前的一些雲建模與渲染的方式。讓我們把兩種方法做個對比:
- 在封包法中我們不真的支持演進式推算策略,因為沒有額外生成錐體和距離場的性能預算。(*圖中標註出了 Pseudomotion Only,只支持偽運動,前面提到過的一個詞)
- 兩種方式都是全天候有效的。
- 光照只在垂直輪廓法中實現了。
- 但兩者都支持高幀率模式。
- 只有封包雲層是支持飛行通過的。
And unfortunately, none of these methods are very visually intuitive to author and work with. Let’s be honest. Those of you who have worked with these methods know what I mean.
不幸的是,兩種方式都不是以符合視覺直覺的方式來製作起效的——實話實說,負責以這些方法制作雲的人知道我在說什麼。
兩種方法中的這些問題都阻止了我們(包括藝術總監)實現最初就想實現的目標——飛越雲層。
因而,在完成了西域禁地的版本開發後——懷著既沮喪又基於證明自己的心情,我開始開發一個原型。在上一年的分享中,我以這一技術的簡短一瞥作為了收尾——被稱為實時體積雲渲染(real-time voxel-cloud renderer)的原型。
2 體積雲渲染原型——A Multi-Voxel Cloud Renderer Prototype
相比於在不確定雲在何處就開始ray-march採樣,我把一個包圍盒和內部有向距離場整合到了原本採樣來源不可知的方法中。
將採樣了密度和光照的多個體積疊加。圖中展示了3層疊加的體積雲效果。
圖中白框範圍展示了這種混合式採樣放置方法。
我獨自嘗試迭代了很多版,直到這一過程(在我個人角度)無法優化得更快為止。
至此好消息是我們可以組合少量的雲層,允許玩家飛進其中(之前只能環繞),在PS5的960x540分辨率下需要4毫秒的開銷。
而不好的——但極度偶然的消息是,因為我把這一結果展示給了藝術總監,現在他讓我回憶起了加入Guerrilla最初就定下的目標。
很快,我就被召集參加了DLC的預告片的會議——聽說展示的內容需要包含一些雲層的技術。
*截至到原型這一步其實性能還是比較極限的。
3 燃燒海岸中面臨的困難——The Burning Shores
圖中,預告片中這一幕需要的雲都被以白色橢圓體表示了——不止是雲層,還需要能高速飛過前景和背景中可見的各處有著波濤狀細節的雲層。(*原文這裡也配了一段視頻,展示了主角的飛行)
在會議後我執行了一次測試,以確認原型在這種使用條件下的性能表現——性能很糟糕,並且細節也不夠好。
幸運的是,我們得知了燃燒海岸DLC會只發布在PS5上,這會為我們減少一些性能上的限制。
之後我和兩位技術主管Jeroen Krebbers和Nathan Vos討論了我們從原型變為可交付版本的可行性。說實話這是一次激烈的討論——出於好的目標。
會議最終確定了一件事,就是如果我們如果在宣傳片中展示了這項效果,我們就需要在遊戲中實現它。
我們也認同如果它無法實施,那麼整個企劃就都會宣告失敗。在幾位同事的幫助下(*原文列出了具體名稱),我們確信了視頻中展示的效果可以最終優化並無損地加入DLC中。
*這裡作者展示了對應的宣傳片,視頻容量太大這裡就不放了。
A few takeaways from that experience: I think it was when I was able to produce an expansive cloudscape with this much variety for this shot, that I realized we had a system that was going to work one way or another.
從這次經驗中能總結出一些takeaway:當我能為這個鏡頭製作出如此豐富的雲的形體時,我意識到我們有了一個無論如何都能生效的系統。(*結合後文來看,是指會被項目上以各種方式來使用)
當我們回顧這個鏡頭時——它在天空一公里的位置,而有人問我是否應該用雲掩蓋住200米高的山頂。藝術總監說“不,留下它”。這使我意識到我們最初的目的,在實際創造某種效果面前或許又沒那麼重要了;我也意識到藝術總監已經開始使用雲系統來作為前景工具,以構建視覺深度了。
同時,當我們觀看了宣傳片的觀眾反饋後,發現人們提到了雲的效果,但沒有任何關於它和實際遊玩相結合的討論——意味著大多數人還只是把這當成一個電影級宣傳片。
這讓人感到既興奮又有點害怕。
燃燒海岸DLC自身背景被設定在洛杉磯的火山群島廢墟。
True to Hollywood, the goal of the project was to deliver bigger than life experiences.
正如好萊塢(的口號一樣),遊戲的目標也是提供一段大於生活的體驗。
自然地,結合正在開發的新技術,我們希望為玩家打開天空的探索——而不止是把它侷限在轉場動畫中使用。
這意味著雲系統不僅要起到之前的細節體積天空盒的作用,玩家要能無縫地從雲上飛入水中。
然而,後來的結果表明,要實現這一效果有著更大的挑戰——比宣傳片中的更大。
*這一段因為有多段播片,可能直接翻譯作者的演講稿會覺得略微缺少了一點上下文。其實作者主要面臨兩個問題,一是宣傳片的體積雲效果,其技術當時沒有達到實機的標準;另外是它們想讓玩家能快速無縫飛過大世界中的雲層,又增加了一些優化上的難度。
結語
Guerrilla的雲系統已經標號到了第3代了,這篇分享的作者也無疑是一個專項領域的特型人才。讀了很多有具體實現願景的渲染文章,我發現無論硬件如何發展,遊戲開發者在新平臺或新項目中想拿出的視覺效果都是有挑戰的(例如之前讀的超凡蜘蛛俠系列的建築LOD,他們就是想在城市建築的呈現上有所突破)——當然一般來說遊戲產品也要取得一定的市場或商業成績,並確實有符合預期的性能表現,才能在SIG這樣層面的大會上去演講。
這篇分享由於圖文都很長,這次算是讀完了承前啟後的部分。下次的中篇會從第三代雲的數學建模開始,逐步深入細節。
最後是資料鏈接:
Nubis3: Methods (and madness) to model and render immersive real-time voxel-based cloud 1080P PPTX PDF