バリューノイズ


title: "バリューノイズ" description: "格子点にランダム値を割り当て、補間することでなめらかなノイズを生成する手法を学びます。" chapter: "07-noise" order: 2 challenge: description: "バリューノイズを使って、グラデーションを歪ませてみましょう。横方向のグラデーション(uv.x)にノイズ値を加算して、ゆらぎのあるグラデーションを作ってください。" hints:

  • "まずは基本のグラデーション float base = uv.x; を作り、そこにノイズを加算します。"
  • "ノイズの影響度を調整するには係数を掛けます。例: base + valueNoise(uv * 5.0) * 0.3"
  • "最終的に vec3 color = vec3(uv.x + valueNoise(uv * 5.0) * 0.3); のように書くと、ノイズで歪んだグラデーションが完成します。"

バリューノイズ

ランダムから「ノイズ」へ

前回学んだ疑似乱数は、ピクセルごとに完全にバラバラな値を返しました。自然界のテクスチャ(雲、山、木の肌)は、完全にランダムではなくなめらかな変化を持っています。

ノイズとは、空間的に連続で滑らかな疑似ランダム関数のことです。近くのピクセル同士は似た値を持ち、離れるにつれて変化します。

バリューノイズの仕組み

バリューノイズは最も単純なノイズ関数です:

  1. 格子点にランダムな値を割り当てる
  2. 格子点の間を補間する
float valueNoise(vec2 st) {
    vec2 i = floor(st);  // 格子点の整数部分
    vec2 f = fract(st);  // 格子内の位置(0.0〜1.0)

    // 四隅のランダム値
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));

    // 補間
    vec2 u = smoothstep(0.0, 1.0, f);

    return mix(
        mix(a, b, u.x),
        mix(c, d, u.x),
        u.y
    );
}

floor と fract

floor(st)fract(st) の役割を理解しましょう:

  • floor(st) — 格子点のインデックス。どのセルにいるかを示す
  • fract(st) — セル内の位置。補間のウェイトに使う

例えば st = vec2(3.7, 2.3) なら:

  • floor = vec2(3.0, 2.0) → 格子点(3, 2)のセル
  • fract = vec2(0.7, 0.3) → セル内の右寄り・やや下

バイリニア補間

4つの格子点の値をバイリニア補間(二方向の線形補間)で混ぜます:

c --- d
|     |
|  p  |    p = 現在のピクセル位置
|     |
a --- b

まず横方向に補間(aとb、cとd)し、次に縦方向に補間します。

smoothstep で滑らかに

単純な線形補間(mix(a, b, f.x))だと、格子点で傾きが不連続になります。smoothstep を使うと、格子の境界で滑らかにつながります:

// 線形補間 — 格子の境目がギザギザ
vec2 u = f;

// smoothstep補間 — 滑らか
vec2 u = smoothstep(0.0, 1.0, f);

// さらに滑らかな補間(quintic)
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);

右のエディタでは、バリューノイズをグレースケールで可視化しています。uv にかけるスケール値を変えると、ノイズの粗さが変わります。

スケール

valueNoise(uv * 5.0) のようにスケールを変えると:

  • 小さい値 → 大きなうねり(低周波)
  • 大きい値 → 細かいノイズ(高周波)

まとめ

  • バリューノイズは格子点のランダム値を補間して作る
  • floor でセル、fract でセル内位置を求める
  • smoothstep で滑らかな補間を実現
  • スケール値で粗さを調整できる