fBm


title: "fBm (Fractal Brownian Motion)" description: "複数のノイズを重ね合わせるfBmを学びます。異なるスケールのノイズを組み合わせて、雲や地形のような複雑なパターンを生成します。" chapter: "07-noise" order: 4 challenge: description: "fBmを使って地形のような見た目を作りましょう。fBmの値に応じて色を段階的に変え、水(青)→砂浜(黄)→草地(緑)→山(茶)→雪(白)のカラーマップを適用してください。" hints:

  • "fBmの値をしきい値で分岐させます。例: n < 0.4 なら水、n < 0.5 なら砂浜..."
  • "smoothstep を使うと境界を滑らかにできます。"
  • "水: vec3(0.1, 0.3, 0.6), 砂浜: vec3(0.8, 0.7, 0.4), 草地: vec3(0.2, 0.5, 0.2), 山: vec3(0.4, 0.3, 0.2), 雪: vec3(1.0) のように設定します。"

fBm (Fractal Brownian Motion)

自然はフラクタル

海岸線、山脈、雲——自然の形はフラクタル的な性質を持っています。大きなスケールの凹凸の上に、小さな凹凸が重なり、さらにその上に細かい凹凸が...という構造です。

1回のノイズでは、1つのスケールの変化しか表現できません。fBm(Fractal Brownian Motion) は、異なるスケールのノイズを重ね合わせることで、フラクタル的な複雑さを生み出します。

fBmの仕組み

基本的な考え方はシンプルです。ノイズを倍々のスケールで計算し、半分の振幅で足し合わせます:

float fbm(vec2 st) {
    float value = 0.0;
    float amplitude = 0.5;    // 振幅
    float frequency = 1.0;    // 周波数

    for (int i = 0; i < 6; i++) {
        value += amplitude * valueNoise(st * frequency);
        frequency *= 2.0;     // 周波数を倍に(lacunarity)
        amplitude *= 0.5;     // 振幅を半分に(gain)
    }
    return value;
}

各ループ(オクターブ)で:

  • 周波数を2倍にする → より細かいスケールのノイズ
  • 振幅を半分にする → 細かいスケールほど影響が小さい

lacunarity と gain

fBmの性質を制御する2つのパラメータ:

| パラメータ | 意味 | 典型値 | |-----------|------|--------| | lacunarity | 周波数の倍率 | 2.0 | | gain (persistence) | 振幅の減衰率 | 0.5 |

frequency *= lacunarity;  // 通常 2.0
amplitude *= gain;         // 通常 0.5
  • lacunarity を上げる → オクターブ間のスケール差が大きくなる
  • gain を上げる → 高周波の影響が大きくなり、よりザラザラに
  • gain を下げる → 高周波の影響が小さくなり、より滑らかに

オクターブ数

ループ回数(オクターブ数)はディテールの細かさを決めます:

  • 1〜2オクターブ — なめらかな丘
  • 4〜6オクターブ — 雲のような複雑さ
  • 8以上 — 非常に細かいディテール(計算コスト高)

実用的には 4〜6オクターブで十分な場合がほとんどです。

雲テクスチャ

右のエディタでは、fBmを使って雲のようなテクスチャを生成しています。fBmの値を色にマッピングすると、非常にリアルな雲が表現できます。

float n = fbm(uv * 3.0 + u_time * 0.1);
vec3 sky = vec3(0.4, 0.6, 0.9);
vec3 cloud = vec3(1.0);
vec3 color = mix(sky, cloud, n);

fBmの応用

fBmは驚くほど多様な表現に使えます:

  • — fBmの値を白と空色の間でマッピング
  • 地形 — fBmの値を高さとして、色で段階表示
  • 水面 — fBmでUV座標を歪ませて波紋を表現
  • — fBmにy方向の減衰と時間変化を加える
  • 大理石sin(x + fbm(...)) で縞模様にノイズを加える

Domain Warping

fBmの結果をさらに別のfBmの入力にするDomain Warpingは、非常に有機的な模様を作れます:

float n = fbm(st + fbm(st + fbm(st)));

まとめ

  • fBmは複数オクターブのノイズを重ね合わせる
  • lacunarity(周波数倍率)とgain(振幅減衰)で性質を制御
  • 4〜6オクターブで十分な複雑さが得られる
  • 雲、地形、水面など自然現象の表現に不可欠