ディストーション


title: "ディストーション" description: "UV座標を変形させるディストーションエフェクトを学びます。波紋や渦巻きなどの座標変形テクニックを習得します。" chapter: "08-textures" order: 4 challenge: description: "渦巻き(Swirl)ディストーションを実装しましょう。中心からの距離に応じて座標を回転させ、渦巻き状にパターンを歪ませてください。" hints:

  • "中心からの距離で回転角度を決めます: float angle = dist * 5.0;"
  • "2D回転の公式: x' = xcos(a) - ysin(a), y' = xsin(a) + ycos(a)"
  • "完成形: vec2 centered = uv - 0.5; float dist = length(centered); float angle = dist * 8.0 - u_time; vec2 rotated = vec2(centered.xcos(angle)-centered.ysin(angle), centered.xsin(angle)+centered.ycos(angle)); vec2 distorted = rotated + 0.5; そしてこの distorted を使ってパターンを描画します。"

ディストーション

UV座標の変形

これまで学んだエフェクトは色の値を変換するものでしたが、ディストーションは座標自体を変形させます。テクスチャやパターンを読み取る前にUV座標を歪ませることで、波紋、渦巻き、レンズ歪みなどの効果が得られます。

// 通常のパターン取得
vec3 color = pattern(uv);

// ディストーション適用
vec2 distortedUV = distort(uv);
vec3 color = pattern(distortedUV);

「色を変えるのではなく、どこを見るかを変える」のがディストーションの本質です。

波紋エフェクト

中心からの距離に応じたsin波で座標をずらします:

vec2 centered = uv - 0.5;
float dist = length(centered);

// 距離に応じた波紋
float wave = sin(dist * 30.0 - u_time * 3.0) * 0.02;

// 中心方向にずらす
vec2 distorted = uv + normalize(centered) * wave;

sin(dist * 周波数) で距離に応じた同心円状の波を作り、その振幅分だけ座標をずらします。u_time を引くことで波が外側に広がるアニメーションになります。

渦巻きエフェクト

中心からの距離に応じて座標を回転させます:

vec2 centered = uv - 0.5;
float dist = length(centered);

// 距離に応じた回転角
float angle = dist * 8.0;

// 2D回転
vec2 rotated = vec2(
    centered.x * cos(angle) - centered.y * sin(angle),
    centered.x * sin(angle) + centered.y * cos(angle)
);

vec2 distorted = rotated + 0.5;

中心に近いほど回転角が小さく、遠いほど大きく回転するので、渦巻き状の歪みになります。

2D回転の復習

2D回転行列を使った座標変換:

vec2 rotate(vec2 p, float angle) {
    float c = cos(angle);
    float s = sin(angle);
    return vec2(p.x * c - p.y * s, p.x * s + p.y * c);
}

この関数は原点中心で回転するので、まず座標を中心に移動してから回転し、元に戻す必要があります。

ノイズディストーション

前章で学んだノイズをディストーションに使うと、有機的な歪みが得られます:

vec2 offset = vec2(
    valueNoise(uv * 5.0),
    valueNoise(uv * 5.0 + vec2(100.0))
);
vec2 distorted = uv + (offset - 0.5) * 0.1;

魚眼レンズ

中心からの距離を非線形に変換すると、魚眼レンズのような効果が得られます:

vec2 centered = uv - 0.5;
float dist = length(centered);
float power = 2.0;
vec2 distorted = 0.5 + normalize(centered) * pow(dist, power);

組み合わせ

ディストーションはチェーンすることができます:

vec2 uv1 = ripple(uv);       // まず波紋
vec2 uv2 = swirl(uv1);       // 次に渦巻き
vec3 color = pattern(uv2);   // 最後にパターン取得

右のエディタでは、チェッカーボードパターンに波紋ディストーションを適用しています。

まとめ

  • ディストーションはUV座標を変形させるエフェクト
  • 波紋 — sin(距離) で放射状の歪み
  • 渦巻き — 距離に応じた回転
  • ノイズで有機的な歪み
  • 複数のディストーションを組み合わせられる