GLSL Tips #01 レイヤーの結合
こんにちは、AQUARING かに です。
WebGLやopenFrameworksなどでGLSLを書くたびに毎回「どうやるんだっけ?」となることが多々あるので、こまめに記事にして備忘録として残していこうと思います。
今回はレイヤーの結合についてです。
距離関数で描いた複数の円を重ねるコードを例に説明していきますが、テクスチャを使ったマスクでも同様の処理でレイヤーを結合できます。
背景レイヤーと結合
precision highp float;
varying vec2 vUv;
// 距離関数:円
float circle2d(vec2 uv, vec2 pos, float r) {
return 1. - smoothstep(r + 0.99, r, length(uv - pos));
}
void main() {
vec2 uv = vUv;
// 背景レイヤー
vec3 color = vec3(0.);// 現在のピクセル色 最初は背景色にしておく
// レイヤー1
float mask1 = circle2d(uv, vec2(.5, .5), .2);// 円形のマスク作成
color = mix(color, vec3(1., 0., 0.), mask1);// マスク部分にだけ円の色(赤)を載せる
gl_FragColor = vec4(color, 1.);
}
まず現在のピクセル色を保存しておくために color という変数に背景色をいれておきます。これが背景レイヤーになります。
vec3 color = vec3(0.);// 現在のピクセル色 最初は背景色にしておく
次に距離関数 circle2d から返ってきた値をレイヤーマスクとして使うため、変数 mask1 に代入しておきます。
ここではキャンバスの中心に半径 0.2 の円形のマスクを作成しています。
float mask1 = circle2d(uv, vec2(.5, .5), .2);// 円形のマスク作成
mix() を使って背景色の上に円の色を載せます。
このとき第三引数にマスクの値をいれることで円の部分にだけ色が載ります。
color = mix(color, vec3(1., 0., 0.), mask1);// マスク部分にだけ円の色(赤)を載せる
複数レイヤーを結合
複数レイヤーになった場合でもやることは簡単で、1レイヤーごとにマスクの作成と mix() を繰り返すだけです。
precision highp float;
varying vec2 vUv;
float circle2d(vec2 uv, vec2 pos, float r) {
return 1. - smoothstep(r * 0.99, r, length(uv - pos));
}
void main() {
vec2 uv = vUv;
// 背景レイヤー
vec3 color = vec3(0.);
// レイヤー1
float mask1 = circle2d(uv, vec2(.5 - 0.1, .5), .2);// ちょっと左にずらす
color = mix(color, vec3(1., 0., 0.), mask1);
// レイヤー2
float mask2 = circle2d(uv, vec2(.5 + 0.1, .5), .2);// ちょっと右にずらす
color = mix(color, vec3(0., 1., 0.), mask2);// 緑色の円を載せる
gl_FragColor = vec4(color, 1.);
}
ちなみに、各レイヤーの mix() の実行順を変えるだけでレイヤーの前後関係を入れ替えることができます。
// レイヤー2
float mask2 = circle2d(uv, vec2(.5 + 0.1, .5), .2);// ちょっと右にずらす
color = mix(color, vec3(0., 1., 0.), mask2);// 緑色の円を載せる
// レイヤー1
float mask1 = circle2d(uv, vec2(.5 - 0.1, .5), .2);// ちょっと左にずらす
color = mix(color, vec3(1., 0., 0.), mask1);
この記事が気に入ったらサポートをしてみませんか?