@natsu1211

ゲーム開発、プログラミング言語の話

水面レンダリングの手法まとめ

リアルな水面レンダリングは、CGとゲーム開発の分野において重要なテーマの一つです。これは比較的に複雑なテーマで、更に以下の課題に分けられます。

  • 波のシミュレーション
  • 水のシェーディング
    • 反射
    • 水の透明感の表現
  • 白い泡(Form)の表現

それぞれの課題に対して様々な手法が提案されてきました。 これらの手法を組み合わせして、初めてリアルな水面レンダリングができるようになります。

波のシミュレーション

水面の形を作るためかなり重要。手法の原理によって、以下のように分類できます。

波の重ね合わせ
  • 正弦波(Sinusoids Wave)[Max 1981]
  • ゲルストナー波(Gerstner Wave)[Fournier 1986]
統計モデル
  • 高速フーリエ変換(Fast Fourier Transform)[Mastin 1987]
  • 空間-スペクトル混合法(Spatial -Spectral Approaches)[Thon 2000]
粒子法
  • Wave Particles [Yuksel 2007]
  • Water Wave Packets [Jeschke 2017]
  • Water Surface Wavelets [Jeschke 2018]
物理ベース
プレレンダリング
  • 頂点高さマップ変位(Vertex Height Map Displacement)[Yuri 2005]
  • フローマップ(Flow Map)[Vlachos 2010]
  • オフラインFFTテクスチャベーキング(Offline FFT Texture)[Torres 2012]
  • オフライン流体フレームアニメーションベーキング(bake to flipbook)[Bowles 2017]
その他
  • バンプマッピング(Bump Mapping)[Schachters 1980]
  • フラクタルノイズ(Fractal Noise)[Perlin 1985]
  • 非整数ブラウン運動(Fractal Brownian Motion, FBM)[Addison 1996]
  • Procedural Shape [Ebert 1999]
  • ボクセルベース(Voxel-Based Solutions)[Yann 2003]
  • 二次元波動方程式(2D Wave Equation)[Nishidate 2005]
  • スクリーンスペースメッシュ(Screen Space Mesh)[Muller 2007]
  • Water Wave Simulation [Grenier 2018]

ゲルストナー波

水の透明感の表現

水面に到達する光線は、水面で反射するだけでなく、一部の光線が水面下に入り、吸収と散乱を経て再び水面から放出される現象があります。これを水のサブサーフェススキャッタリング(Sub-Surface Scattering, SSS)現象と呼びます。

物理ベースのレンダリングでは、サブサーフェススキャッタリングを再現する最も標準的な方法は、BSSRDF(Bidirectional Surface Scattering Reflectance Distribution Function、双方向散乱面反射率分布関数)を解くことです。しかし、BSSRDFを解くには膨大な計算量が必要なため、リアルタイムレンダリングが必要なゲームでは、依然として非物理的な経験則レンダリング方法が主に使用されています。

BSSRDF
主流のアプローチは以下の2つあります。

  • 深度色対応表法(Depth Based Look-Up-Table Approach)
  • SSS近似法(Sub-Surface Scattering, SSS Approximation Approach)
Depth Based Look-Up-Table

考え方として、カメラ方向の水のピクセルの深さを計算し、その深さ値に基づいて吸収/散乱LUT(Absorb/Scatter LUT)テクスチャをサンプリングすることで、異なる深さの水の色付けを制御します。

Depth Based LUT法

SSS Approximation

SSSを表現するための近似手法はたくさんありますが、ここで2つ例をあげます。

  • Crest Ocean System [SIGGRAPH 2019]
  • FrostbiteエンジンのFast SSS [GDC 2011]

白い泡の表現

波打ちや船が通過する際、波の一部や船の周辺の水が白くに見えます。これは水に大量の空気が混入し、すべての入射光が反射され、下にあるものに光が透過しなくなるからです。 この白い泡を表現できるかどうかも水面がリアルにみえるかどうかの重要なポイントです。

主な手法は以下にようになります。

  • ヤコビ行列に基づく手法 [Tessendorf 2001]
  • Saturate高さに基づく手法 [GPU Gems 2]
  • シーン深さに基づく方法 [Siggraph 2018][Sea of Thieves]
  • Noise Texture + Flow Map [GDC 2018][Far Cry 5]

水面レンダリングOSS

Crest Ocean System
https://github.com/wave-harmonic/crest

CryEngine
https://github.com/ValtoGameEngines/CryEngine/blob/release/Engine/Shaders/HWScripts/CryFX/Water.cfx

UE4 Dynamic Water
https://github.com/marvelmaster/UE4_Dynamic_Water_Project_V3

Unity BoatAttack
https://github.com/Unity-Technologies/BoatAttack