以下の記事と似た方向の記事で、自分がよく使っている p5.js のフィルター用シェーダー「createFilterShader()」の話です。
●p5.js のフィルター用シェーダー「createFilterShader()」で Webカメラ画像をそのまま出力(テンプレート的なもの、WebGL 2.0/GLSL ES 3.0) - Qiita
https://qiita.com/youtoy/items/cbd16903cbb14e49662a
シェーダーで、p5.js のスケッチ側から渡したピクセルの情報を使い、それに特定の値を加算・減算する処理を使うことが良くあるのですが、今回はそのような構成のものをわりとシンプルにした内容という感じです。
何らか、シェーダーによる加工を試す際に、そのベースとして利用するテンプレート的なものを自分用に用意したくなり、今回の内容を書きました。
メインの内容
固定値の減算
以下が今回の内容の 1つ目です。
フラグメントシェーダーは、公式サンプルと違って「WebGL 2.0(GLSL ES 3.0)」を使う形にしています。
let s;
function setup() {
createCanvas(640, 480);
s = createFilterShader(fragSrc);
}
function draw() {
background(220);
filter(s);
}
const fragSrc = `#version 300 es
precision mediump float;
in vec2 vTexCoord;
out vec4 outColor;
uniform sampler2D tex0;
void main() {
vec4 color = texture(tex0, vTexCoord);
color.rgb = color.rgb - vec3(100.0 / 255.0);
color.rgb = clamp(color.rgb, 0.0, 1.0);
outColor = color;
}`;
色の処理に関わる部分は、以下のとおりです。
...
function draw() {
background(220);
...
}
const fragSrc = `#version 300 es
...
void main() {
vec4 color = texture(tex0, vTexCoord);
color.rgb = color.rgb - vec3(100.0 / 255.0);
color.rgb = clamp(color.rgb, 0.0, 1.0);
outColor = color;
}`;
毎回、背景をグレースケール(値は 0〜255)の 220 の値にして、そこから固定の値を減算します。減算する値は、以下のとおり 255段階のうちの 100 です。
color.rgb = color.rgb - vec3(100.0 / 255.0);
color.rgb = clamp(color.rgb, 0.0, 1.0);
それを、RGB の全てで減算しています。
※ グレースケールなので、元の値は RGB とも同じ値
その際、シェーダーの処理の上で 0〜1.0(ピクセルの値では 0〜255 の値)におさまるように「clamp()」の処理を入れています(今回の例では不要ですが)。
これを実行した結果は、以下のとおりです。
場所に応じた値の減算
以下が今回の内容の 2つ目です。
次は、減算する値を固定値ではなく、左上が 10 で右下が 200 となるような、グラデーションのある値の減算とします。
実装した内容は以下のとおりです。
let s;
function setup() {
createCanvas(640, 480);
s = createFilterShader(fragSrc);
}
function draw() {
background(200);
filter(s);
}
const fragSrc = `#version 300 es
precision mediump float;
in vec2 vTexCoord;
out vec4 outColor;
uniform sampler2D tex0;
void main() {
vec4 color = texture(tex0, vTexCoord);
// 減算する値が、左上が10で右下が200となるようにする
float subtractValue = mix(10.0, 200.0, (vTexCoord.x + vTexCoord.y) / 2.0) / 255.0;
color.rgb = color.rgb - vec3(subtractValue);
color.rgb = clamp(color.rgb, 0.0, 1.0);
outColor = color;
}`;
以下がポイントになる箇所です。
float subtractValue = mix(10.0, 200.0, (vTexCoord.x + vTexCoord.y) / 2.0) / 255.0;
出力した結果は、以下のとおりです。
右下にいくにしたがって減算する値が大きくなるので、左上から右下に向かうにつれて、だんだん色が暗くなっていきます。