水・地形・植生

ゲルストナー波

Gerstner Waves

頂点を水平と垂直に動かして盛り上がる波を作る。

1 / 10

インタラクティブデモ

デモを準備しています…

ゲルストナー波

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

ひとことで

水面の頂点を上下だけでなく前後にも円を描くように動かして、波頭の尖った海の波を作る方法です。正弦波で上下に揺らすだけだと山も谷も同じ丸い形になりますが、ゲルストナー波では水の粒が山で前へ寄り集まり、谷で離れるので、本物の海のように山は鋭く、谷は平らになります。

ゲームでの使いどころ

  • 海や湖の水面:船が進む海原、港、ビーチ。頂点変位だけで作れるので、多くのゲームで海の基本形として使われます。
  • CPU と GPU で同じ波を計算できる:波の式が単純なので、描画用の頂点シェーダーと、船を浮かべる浮力の計算で同じ高さを求められます。見た目と物理がずれません。
  • 波頭の泡:水面がどれだけ縮んだか(ヤコビアン)も式から求まるので、尖った波頭だけを白く泡立たせられます(ホワイトウォーター)。
  • 遠景とのつなぎ:近くはゲルストナー波、遠くは法線マップだけ、という使い分けがよく行われます。

しくみ

水面上の元の位置 x0=(x,z)\mathbf{x}_0 = (x, z) にある点を、次の位置へ動かします。

x=x0+∑iQiAidicos⁡θi,y=∑iAisin⁡θi,θi=ki di⋅x0−ωit+φi\mathbf{x} = \mathbf{x}_0 + \sum_i Q_i A_i \mathbf{d}_i \cos\theta_i, \qquad y = \sum_i A_i \sin\theta_i, \qquad \theta_i = k_i\, \mathbf{d}_i \cdot \mathbf{x}_0 - \omega_i t + \varphi_i
  • AiA_i は振幅、di\mathbf{d}_i は進む向き、ki=2π/λik_i = 2\pi / \lambda_i は波数(波長 λi\lambda_i の逆数)、φi\varphi_i はばらばらの初期位相です。
  • ωi=gki\omega_i = \sqrt{g k_i}(深い海の分散関係)とすると、長い波ほど速く進むという本物の海の性質が再現されます。
  • 水平方向の項 QiAidicos⁡θiQ_i A_i \mathbf{d}_i \cos\theta_i があるので、各点は縦の円(Q=1Q=1 で真円)を描きます。山(sin⁡θ=1\sin\theta = 1)では cos⁡θ=0\cos\theta = 0 付近で点が前へ寄り、尖ります。

波の向きや長さを少しずつ変えて 4〜12 本ほど重ねると、規則的すぎない海面になります。多くの場合、風向きの周りに向きを散らし、波長の短い波ほど振幅を小さくします。

尖り QQ の上限に注意します。∑iQikiAi>1\sum_i Q_i k_i A_i > 1 になると、隣の点を追い越して水面が裏返り、輪(ループ)ができてしまいます。そこで、各波の QiQ_i を「全体の尖り ÷(kiAi×k_i A_i \times 波の本数)」とし、合計が 1 を超えないようにします。

実装のポイント

  • 法線は解析的に:式を微分すれば法線が求まるので、周りの頂点から差分で計算する必要はありません。細かい波は頂点を増やさず、法線にだけ足す(または法線マップを重ねる)とコストを抑えられます。
  • ある地点の水面の高さ:点は水平にも動くので、(x,z)(x, z) の真上の高さは式にそのまま代入しても求まりません。「代入 → ずれた分だけ戻す」を数回くり返して、元の位置を逆算します(浮力の計算で必要になります)。
  • タイル状の繰り返しを隠す:本数が少ないと周期が目立ちます。互いに割り切れない波長を選び、遠くは霧や空気遠近法でぼかします。

つまずきやすい点

  • 尖らせすぎて水面が裏返る:尖りを上げすぎると、波頭で三角形が裏返ってちらつきます。上に書いた QQ の正規化を入れます。
  • 頂点が足りない:波長より頂点の間隔が粗いと、波がカクカクに折れて見えます。カメラの近くほど細かい格子(LOD)にします。
  • 法線を変位前の位置で使う:シェーダーで法線を計算し忘れると、形は波打っているのに陰影が平らなままになります。

デモで試すこと

  1. 「波の動かし方」を「正弦波(上下だけ)」に切り替えると、山も谷も同じ丸い形になります。「ゲルストナー波(円運動)」に戻すと、山が尖り谷が広がります。
  2. 光る点の列は、最初は一直線に並んだ水の粒です。波が通るたびに縦の円を描いて元に戻る様子と、山の所で点が詰まる様子を見てください。
  3. 「尖り具合 Q」を 0 にすると正弦波と同じになり、1 に近づけるほど波頭が鋭くなります。
  4. 「重ねる波の数」を 1 にすると、規則正しい 1 本の波になります。本数を増やすほど自然な海に近づきます。

参考資料

GPU Gems — Effective Water Simulation ↗

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