自行掌控遊戲光線表現的純 Shader 無材質實驗

· 2316 字 · 5 分鐘

2021 年初在完成遊戲 AI 的翻新後,決定放自己一長段時間的假暫時不要想現在遊戲專案的開發。於是二月、三月、四月期間我做了一系列無關手上專案的遊戲實驗。

三月的時候我研究起了能怎樣在短時間內建構一個能被有效使用的世界,不過當時日本政府國土交通省正巧公布了一個全國都市建模計畫,可以說是與上面研究的部分內容重疊甚至讓上面的研究變得不必要。

於是我一邊有點悻悻然地整理成果寫起了工作流程研究文章,一邊構思接下來該研究什麼才好。於是四月時就將研究轉移到奠基於前述既有建模,能怎樣拿來利用的部分。

完整的東京 23 區建模 🔗

Plateau 計畫是一個要將全日本都市都進行建模的土木計畫。這個大前提代表了幾件事情:

  • 土木用途為重,例如說疏洪防災的模擬計算,資料完全不是為了遊戲而準備的
  • 也畢竟是土木用途為重,建模品質並無一致
    • 大約只有一成以下的建模是 LOD 2 級(形狀完全正確,附加低解析度材質)
    • 其餘則是 LOD 1 級(只有外框形狀正確)

也因此說是與前述工作流程部分重疊而已,因為要根據這樣的資料做成能用的場景還是需要進行相當的額外處理。

截止到現在為止,全國的建模都已經被公布了,而今年三月公布這個計畫的初期成果是東京 23 區的完整建模。那一成的精細建模還附贈超大的材質,而就算用上了幾 GB 的材質,實際上也只是低解析度的平面貼圖,近看完全不行。

因而讓我想研究能怎樣以此為基礎延伸。

但也先說現階段我完全不建議任何人嘗試以 Plateau 的建模資料去製作遊戲。光是要放進去 Unity 正常執行就很折騰了 XD

純 Shader 的無材質表現 🔗

去年底的時候因為 Digital Foundry 的介紹讓我注意到了《空戰獵鷹》這款遊戲,這款遊戲只使用了 Shader,甚至所有的 UI 都是用 Shader 寫出來的成果而沒有使用到任何材質。唯一的例外是因為主機效能問題生成海洋的雜訊有事先生成出來的材質。

雖然遊戲性本身並不是我特別喜歡的部分,但是視覺表現的部分卻相當驚人,也因為是純 Shader 表現的而能以一人之姿完成這款開放世界遊戲。在追蹤了解的訪問中可以了解到一些這個實作能帶來的性質與好處:

  • 遊戲裡面所有光線表現都獨立於 Unity 本身的光線渲染,也就是不受光,因此可以很有目的性地表現出理想的視覺
  • 由於完全不使用材質,所以整個遊戲的記憶體需求極小,小到他可以一次性載入整個開放世界不用進行效能管理
  • 大部分的 Shader 表現具備自動化的性質,像是根據在世界中的高度決定雪、草的密度,因此他可以著重在建模出正確的形狀就好,丟進去遊戲裡就會自動看起來正確

雖然作者也說做出一套可以完全覆寫掉 Unity 光線表現的機制就花了他一整年,但成果就是可以一人做出相當規模又有特色的開放世界。符合我之前做的研究,能夠相對低(人力)成本地實現高品質的表現。

實驗 🔗

由於我原本三月的研究就已經覆蓋到了只仰賴 Shader 表現建物,這次全面性的光線表現覆寫實驗中,我想要做性質更加歧異的方向。

於是就決定表現看看沉在水底的都市樣貌。

目標就是從素模:

original

變成這樣:

result

實作 🔗

以下就開始講述一些為了模仿水下表現而嘗試的東西。由於我的 Shader Code 研究還不夠充分,因此實驗中是使用 Unity 2020.2 的 Shader Graph 製作。但也代表說下述東西全都不需要任何技術知識就能使用:

波紋 🔗

應該有很多人在觸及水面 Shader 時都已經知道了,Voronoi 圖姑且可以表現出像是水的波紋的感覺。在這個例子中,對於所有 Shader 都進行一個上往下的正投影表現。

caustic

沙子 🔗

基本上沙子有與無的堆積可以使用 Gradient Noise 的密度去表現,根據世界高度來決定就可以輕易表現出來。

sand

沙丘 🔗

同樣根據 Gradient Noise,只要調整地板模型的頂點就可以營造出高低起伏。

sand

遠景漸層 🔗

這部分用了一個從《空戰獵鷹》作者學來的手段:直接在玩家周圍圍一顆半透明的球,寫一個 Shader 根據鏡頭距離控制這顆球的顏色、透明度,將顏色分別漸變兩次。這顆球也就充當 Sky Sphere 使用,寫了一個表現水面波紋的表現。

gradient

sphere

閃爍的沙粒 🔗

波紋所使用的是 Voronoi 圖的邊線,將它倒轉的話就變成了「點」。過去曾經用來仿造星空,用來散播某種性質的不規則點,拿來當閃爍的沙粒也非常適用。

shiny sand

三天實驗的測試,全部加在一起就變成了這樣:

result in motion

最後完成的 Shader 基本上就是有一些共同使用的子 Shader 去固定處理像是波紋的投影表現,確保跨 Shader 之間呈現出來的波紋是一致的。

延伸 🔗

這裡流水帳地提一堆可以額外改良的空間:

  • 波紋不需要只用正投影,可以根據時間變化有角度的改變
  • 所有表現都可以納入深度會降低光線概念處理
  • 任何雜訊都可以用好幾層雜訊去疊,避免高處觀看時會有規律感

而最後,確實依然可以說這樣的畫面還是缺乏精細感,也因此或許不需要正面對決,而是可以刻意使用低解析度表現:

pixelated

可能要點開來比較好看清楚 XD

《A Short Hike》的低解析度完全是為了隱藏表現能力的不足,但也沒有因此而影響遊戲體驗,反而增加了相對於有限解析度的圓滿感。在玩家太容易被畫面精細度、密度影響評價的時代中,顯然是個有價值可以利用的手段。

結論 🔗

《空戰獵鷹》的作者說他「當年為《上古卷軸五》製作模組時發現只要使用雜訊就能表現出雪」而感到感動。確實在這次的實驗中我也覺得相當地有趣,無論是哪種表現,實際上都只需要靠雜訊、投影就可以輕易製作出有趣的視覺效果。

雖然精細度、密度上比起 3A 作品遠遠不足,但也無妨,這樣的手段反而可以確保僅僅一人的願景得以實現,而不需要永遠只感嘆於人力上的不足而難以行動。

當然像這樣的表現也只適合用在幾乎仰賴環境光源的設定,例如說如果要自己寫一套機制可以讓街燈等光源真正提供顏色的話會比較麻煩,這就是需要取捨的地方了。

大概這樣提供參考。

如果願意聽英文的話,最近《空戰獵鷹》的作者有一部非常詳盡的訪談影片,基本上可以說是只要照著這部影片逐步實作,就可以完成一個視覺跟《空戰獵鷹》同等級的作品 XD

只是要完善化配色、用自己的方式覆寫掉整個光線表現或許會需要跟作者一樣就使用上至少一年以上的時間,但在那之後就會換來一套可以自由創作的開放世界的空間了。