ひとことで
風の強さと向きから「どの長さ・向きの波がどれだけあるか」(波のスペクトル)を決め、何千〜何万もの波を高速フーリエ変換(FFT)で一度に足し合わせて海面を作る方法です。映画『タイタニック』の海で使われた Tessendorf の手法として知られ、今では多くのゲームの海の標準的な作り方になっています。
ゲームでの使いどころ
- 広く自然な外洋:船や海戦のゲーム、オープンワールドの海。数本の波を重ねるゲルストナー波では出せない、細かく不規則な波が得られます。
- 天候による変化:風速のパラメータを変えるだけで、凪からしけまで海の表情が変わります。
- タイルとして敷き詰める:FFT で作った海面は端と端がつながる(周期的)ので、同じタイルを並べて無限の海にできます。大きさの違うタイルを数枚重ねると繰り返しが目立ちません。
- 泡や法線も同時に:高さと一緒に、水平方向のずれ・法線・波頭の縮み具合(泡の量)も FFT で求められます。
しくみ
- スペクトルを作る:波数ベクトル (波の向きと細かさ)ごとに、その波の強さを Phillips スペクトルなどで決めます。
は風速、 は風向きです。 は「この風で育つ一番大きなうねり」の長さで、風が強いほど長い波が強くなります。 で、風と同じ向きの波ほど強くします。
-
初期の振幅にばらつきを与える:各 について、ガウス乱数 を使って とします。これは最初に 1 回だけ計算します。
-
時間とともに位相を回す:深い海の波は の速さで進むので、毎フレーム
とします。2 項目は、結果の高さが実数になるようにするための対の成分です。
-
逆 FFT で高さに戻す: の格子(例:)を逆 FFT すると、海面の高さの格子が得られます。 個の波を普通に足すと かかりますが、FFT なら で済みます。
-
波頭を尖らせる: も逆 FFT すると、各点の水平方向のずれが得られます。これを足すと、ゲルストナー波と同じように山が尖ります(「チョッピー波」)。
実装のポイント
- GPU で計算する:実際のゲームではコンピュートシェーダーで FFT を行い、バタフライ演算の各段をピンポンバッファで往復させます。 でも 1 ms 程度で済みます。
- 格子の符号に注意:逆 FFT の結果は、1 マスおきに符号が反転した形で出てくることがあります(原点を中央に置いたスペクトルの場合)。 を掛けて戻します。
- 複数の大きさのタイルを重ねる:例えば 250 m、37 m、5 m の 3 種類を足すと、うねりから小さなさざ波までそろい、繰り返しの周期も目立たなくなります。
つまずきやすい点
- 格子より短い波の扱い:スペクトルは格子の細かさまでしか表現できません。さらに短い波は、法線マップや細かいタイルで補います。
- チョッピー波の上げすぎ:横方向のずれを大きくしすぎると、水面が裏返ります。縮み具合(ヤコビアン)が負になる所を泡として白くし、係数を抑えます。
- 風速の単位: は風速 20 m/s で約 40 m になり、タイルの大きさを超える波は表現できません。タイルの大きさと風速の範囲を合わせます。
デモで試すこと
- 右下のスペクトル画像は、中心が長い波、外側が短い波の強さです。「風速」を上げると、中心付近(長いうねり)が強くなり、海面の起伏が大きくなります。
- 「風向き」を変えると、スペクトルの明るい方向が回り、波が進む向きがそろって変わります。
- 「波頭の尖り」を 0 にすると、丸い波になります。上げるほど山が細く鋭くなります。
- 「タイルの継ぎ目を表示」をオンにすると、同じ 32 m 四方のタイルを並べていることが分かります。継ぎ目で波がとぎれずにつながっているのが FFT 海洋の特徴です。