畳み込み


title: "畳み込み" description: "畳み込み(Convolution)の概念を学びます。カーネルを使ったぼかしやエッジ検出の原理を理解し、プロシージャルパターンに適用します。" chapter: "08-textures" order: 3 challenge: description: "シャープ化エフェクトを実装しましょう。シャープ化カーネル(中央が5、上下左右が-1)を使って、プロシージャルパターンのエッジを際立たせてください。" hints:

  • "シャープ化カーネルの中央は5.0、上下左右は-1.0です。ぼかしカーネルとは値が異なります。"
  • "カーネル: center=5.0, neighbors=-1.0。元のパターン関数で各オフセット位置の値を取得し、カーネルで重み付けします。"
  • "result = pattern(uv)*5.0 - pattern(uv+vec2(px,0)) - pattern(uv-vec2(px,0)) - pattern(uv+vec2(0,px)) - pattern(uv-vec2(0,px)); のように計算します。"

畳み込み

畳み込み(Convolution)とは

畳み込みは画像処理の基本操作です。あるピクセルの新しい値を、その周辺ピクセルの値をカーネル(フィルタ)で重み付けして合計することで求めます。

   周辺ピクセル        カーネル(3x3)
   [a] [b] [c]      [k1] [k2] [k3]
   [d] [e] [f]  ×   [k4] [k5] [k6]
   [g] [h] [i]      [k7] [k8] [k9]

   結果 = a*k1 + b*k2 + c*k3 + d*k4 + e*k5 + f*k6 + g*k7 + h*k8 + i*k9

カーネルの値を変えることで、ぼかし、エッジ検出、シャープ化など、さまざまなエフェクトが実現できます。

ぼかし(Box Blur)

最もシンプルなぼかしはBox Blurで、周辺ピクセルの単純平均を取ります:

カーネル:
[1/9] [1/9] [1/9]
[1/9] [1/9] [1/9]
[1/9] [1/9] [1/9]
float boxBlur(vec2 uv, float radius) {
    float px = radius / u_resolution.x;
    float sum = 0.0;

    for (float x = -1.0; x <= 1.0; x += 1.0) {
        for (float y = -1.0; y <= 1.0; y += 1.0) {
            sum += pattern(uv + vec2(x, y) * px);
        }
    }
    return sum / 9.0;
}

エッジ検出

ラプラシアンカーネルは中央と周囲の差を求め、変化が大きい部分(エッジ)を検出します:

カーネル:
[ 0] [-1] [ 0]
[-1] [ 4] [-1]
[ 0] [-1] [ 0]
  • 均一な領域 → 合計は0に近い(暗い)
  • エッジ部分 → 合計が大きい(明るい)

シャープ化

シャープ化カーネルはエッジ検出の結果を元画像に足し合わせたものです:

カーネル:
[ 0] [-1] [ 0]
[-1] [ 5] [-1]
[ 0] [-1] [ 0]

これは「元画像 + エッジ」と等価です。エッジ部分のコントラストが強調されて、くっきりした見た目になります。

プロシージャルパターンでの畳み込み

通常、畳み込みはテクスチャサンプリングで実装しますが、プロシージャルパターンなら関数を複数回呼び出すことで同じ効果が得られます:

float pattern(vec2 uv) {
    // 何らかのプロシージャルパターン
    return sin(uv.x * 20.0) * sin(uv.y * 20.0) * 0.5 + 0.5;
}

// ぼかし適用
float px = 2.0 / u_resolution.x;
float blurred = 0.0;
for (float x = -1.0; x <= 1.0; x += 1.0) {
    for (float y = -1.0; y <= 1.0; y += 1.0) {
        blurred += pattern(uv + vec2(x, y) * px);
    }
}
blurred /= 9.0;

右のエディタでは、プロシージャルなドットパターンにBox Blurを適用しています。

ガウシアンブラー

より高品質なぼかしにはガウシアンブラーを使います。中央に近いピクセルほど重みが大きく、自然なぼかしになります:

カーネル(近似):
[1/16] [2/16] [1/16]
[2/16] [4/16] [2/16]
[1/16] [2/16] [1/16]

まとめ

  • 畳み込みは周辺ピクセルをカーネルで重み付け合計する操作
  • Box Blur — 均等な平均でぼかし
  • ラプラシアン — エッジ検出
  • シャープ化 — エッジ強調
  • プロシージャルパターンなら関数の複数回呼び出しで実現可能