水・地形・植生

浅水波モデル

Shallow Water Equations

浅い水の高さと流れを計算する。

3 / 10

インタラクティブデモ

デモを準備しています…

浅水波モデル

ドラッグで視点を回転、Ctrl(⌘)+ スクロールでズーム。タッチ操作は 2 本指です。

ひとことで

水を「各マスの水の深さ」と「隣のマスへの流れ」だけで表し、高い所から低い所へ流れ下る様子を格子の上で計算する方法です。3 次元の流体をまともに解くより桁違いに軽く、それでいて洪水、決壊、川の流れ、水たまりができる様子をそれらしく再現できます。

ゲームでの使いどころ

  • 地形に沿って流れる水:ダムの決壊、洪水、溶岩流、泥流。水が谷を走り、くぼみにたまる様子がそのまま出てきます。
  • 掘ると水が流れ込むゲーム:地形を掘ったり盛ったりできるサンドボックスや街づくりで、水路を作って水を引く遊びに使われます。
  • 侵食と組み合わせる:流れの速さが分かるので、速い所で地面を削り、遅い所に土を落とすと水食侵食になります。
  • GPU で広い範囲を:各マスの計算は隣しか見ないので、GPU で並列に計算しやすく、数百 m 四方の水をリアルタイムで動かせます。

しくみ

水平方向の広がりに比べて水深が浅いなら、水の中の上下の動きは無視でき、「水の柱」の高さと水平の流れだけを考えればよくなります。これが浅水方程式です。ゲームでは「パイプモデル」という分かりやすい近似がよく使われます。

  1. 隣へ流れ出す量(流量)を更新する:各マスと隣のマスの間に細いパイプがあると考えます。水面の高さ(地面 + 水深)の差があるほど、パイプの流れが加速します。
f右←max⁡ ⁣(0,  f右+Δt g A (b+d)−(b右+d右)ℓ)f_{\text{右}} \leftarrow \max\!\Big(0,\; f_{\text{右}} + \Delta t\, g\, A\, \frac{(b + d) - (b_{\text{右}} + d_{\text{右}})}{\ell}\Big)

bb は地面の高さ、dd は水深、gg は重力、AA はパイプの断面、ℓ\ell はマスの間隔です。前の流量を残す(慣性)ので、水は勢いよく流れ、行き過ぎて波にもなります。

  1. 持っている水より多くは流さない:4 方向の流出の合計が、そのマスの水の量を超える場合は、比率を保ったまま縮めます。これがないと水深が負になります。

  2. 水深を更新する:流れ込んだ量と流れ出た量の差で水深を変えます。

d←d+Δtℓ2(∑f流入−∑f流出)d \leftarrow d + \frac{\Delta t}{\ell^2}\Big(\sum f_{\text{流入}} - \sum f_{\text{流出}}\Big)
  1. 流速を求める(必要なら):左右の流量の差から水平の速度が分かります。泡を出す、物を流す、侵食する、などに使います。

水の量が「流れ出た分だけ隣に入る」形で受け渡されるので、水の総量が保存されるのがこの方法の大きな長所です。

実装のポイント

  • 2 つのループに分ける:流量を全部更新してから水深を更新します。1 つのループで混ぜると、計算順によって結果が偏ります。GPU ならピンポンバッファで読み書きを分けます。
  • 時間刻み:水面の波は gd\sqrt{g d} の速さで伝わります。1 ステップで波が 1 マス以上進むと不安定になるので、Δt<ℓ/gdmax⁡\Delta t < \ell / \sqrt{g d_{\max}} を目安に分割します。
  • 描画:水面は地面の上に水深を足した高さの格子で描き、深さで色を変えます。水深がほぼ 0 のマスは地面の下に沈めて隠します。

つまずきやすい点

  • 浅い水が地面から浮いて見える:乾いた所と濡れた所の境目で水面がぎざぎざになります。水深がしきい値以下のマスを隠す、水面メッシュの頂点を地面に合わせる、などで目立たなくします。
  • 水が止まらずに揺れ続ける:減衰を入れないと、たまった水がいつまでも波打ちます。流量に 1 よりわずかに小さい係数を掛けます。
  • 砕ける波や滝は苦手:高さ 1 つで表すので、水が覆いかぶさる形(巻き波)や垂直な滝は表現できません。そこは粒子やSPHなど別の方法と組み合わせます。

デモで試すこと

  1. 「ダムを決壊させる」を押すと、貯水池の水が谷を走り下り、下流のくぼみにたまっていきます。「水の量」の数値がほとんど変わらないこと(保存されていること)も確かめてください。
  2. 「水の色」を「流れの速さ」にすると、谷の狭い所や急な所ほど速く流れているのが分かります。
  3. 地形をクリックすると、その場所に水を注げます。尾根に注ぐと両側の谷へ分かれて流れます。
  4. 「雨を降らせる」をオンにすると、全体に少しずつ水が増え、低い所から順に水たまりができていきます。

参考資料

GPU Gems — Effective Water Simulation ↗

分野全体の資料で、この項目を直接扱っているとは限りません。