LoginSignup
2
1
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

p5.js の createFilterShader() を使ったフィルター用シェーダーのお試し

Last updated at Posted at 2024-01-07

はじめに

今回の内容は、p5.js の createFilterShader() のお試しです。

createFilterShader() とは?

createFilterShader() がどういうものかという話は、以下の公式リファレンスで説明されています。

●reference | createFilterShader()
 https://p5js.org/reference/#/p5/createFilterShader

image.png

冒頭の説明を見てみると、「using only a fragment shader, as a convenience method for creating image effects.」と書いてあります。
その説明内容は、「フラグメントシェーダーを利用するだけで、シェーダーの処理が行えて、画像エフェクトを使うのに便利」というものです。

p5.js でのシェーダーを使う場合の準備

「フラグメントシェーダーを利用するだけで...」という部分は、少し補足すると「バーテックスシェーダーの準備が不要」ということになります。
p5.js でシェーダーを利用する場合、createShader() を使う方法があり、そしてこの createShader() を使う場合は、バーテックスシェーダーとフラグメントシェーダーを準備する必要がありました。

●reference | createShader()
 https://p5js.org/reference/#/p5/createShader

createFilterShader() を使う場合は、バーテックスシェーダーが準備済みの状態となるようで、そのため自前で用意するのはフラグメントシェーダーだけとなるようです。

試してみた内容

createFilterShader() を使った描画

ここで createFilterShader() を使った描画を先に掲載してみます。

以下の動画では、4つの図形が動いており、その中の図形 2つの色が途中で変化しています。
これは、画面の中のピクセルに対する処理をシェーダーを用いて行っているためです。

処理内容は、画面内のピクセルで RGB の G(緑)の値が一定以上の大きさの場合、色の変更を行っています。この変更処理の ON/OFF は、ユーザーの操作で実行するようにしています。そして、以下の動画では、その ON/OFF の切り替えを何度か行っています。

実装内容

実際に実装した内容は以下のとおりです。

const colorList = ["#3f616c", "#6baec5", "#9dcebc", "#e0e8a4"];

let isF = true;

function setup() {
  createCanvas(500, 400);
  noStroke();

  // ------------------------
  let fragSrc = `precision highp float;

  varying vec2 vTexCoord;
  uniform sampler2D tex0;

  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
	if (color.g > 0.8) {
	  gl_FragColor = vec4(color.r = 0.85, color.g= 0.9, color.b = 0.95, 1.0);
	} else {
      gl_FragColor = vec4(color);
	}
  }`;
  s = createFilterShader(fragSrc);
  // ------------------------
}

function draw() {
  background(0);

  // 円1つ目
  const x = width * 0.5 + width * 0.22 * cos(frameCount / 25),
    y = height * 0.5 + height * 0.25 * sin(frameCount / 36);
  fill(colorList[0]);
  circle(x, y, height * 0.22);

  // 矩形
  const x2 = width * 0.6,
    y2 = height * 0.3 + height * 0.2 * sin(frameCount / 27);
  fill(colorList[1]);
  rect(x2, y2, height * 0.22);

  // 円2つ目(大きい方)
  push();
  translate(width / 2, height / 2);
  rotate(frameCount / 30);
  fill(colorList[2]);
  circle(50, 50, height * 0.33);
  pop();

  // 三角形
  push();
  translate(width / 2, height / 2);
  rotate(frameCount / 40);
  translate(width * 0.1, 0);
  fill(colorList[3]);

  triangle(0, 0, height * 0.35, 0, 0, height * 0.35);
  pop();

  if (isF) filter(s);
}

function mouseClicked() {
  isF = !isF;
}

上記の中で、createFilterShader() に関わる部分は、主に // ------------------------ で囲まれたところです。

その中でも、処理のメインの内容は以下です。
この処理では、キャンバス上の色を、デフォルトで準備された「vTexCoord と tex0」を用いて取得しています。

その取得した色を元に、 if (color.g > 0.8) の条件にマッチしたピクセルの色を gl_FragColor = vec4(color.r = 0.85, color.g= 0.9, color.b = 0.95, 1.0); という特定の色にしています。

  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
	if (color.g > 0.8) {
	  gl_FragColor = vec4(color.r = 0.85, color.g= 0.9, color.b = 0.95, 1.0);
	} else {
      gl_FragColor = vec4(color);
	}
  }`;

なお、シェーダーを適用する部分は、 draw() の中の filter(s) の部分です。

このようにして、createFilterShader() を使ったシェーダーの適用を行いました。

補足

デフォルトで用意されるバーテックスシェーダーについて

バーテックスシェーダーはデフォルトで用意されると書きました。
それに関連して利用できる変数は、公式リファレンスに書かれた以下となります。

image.png

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1