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 — 均等な平均でぼかし
- ラプラシアン — エッジ検出
- シャープ化 — エッジ強調
- プロシージャルパターンなら関数の複数回呼び出しで実現可能