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

p5.js のフィルター用シェーダー「createFilterShader()」を使ってメインキャンバスとオフスクリーンキャンバスの描画をまぜる

Last updated at Posted at 2024-01-19

はじめに

以下の「p5.js の createFilterShader()」を扱った 3つの記事に引き続き、また 「createFilterShader() を扱います(この createFilterShader() を使ったシェーダーをあれこれ試すことに、個人的にハマり中ですw)。

今回は、以下の内容をやろうとした過程で、試した内容の 1つです。
(以下は、今回のオフスクリーンキャンバスの描画をシェーダーで使うという内容に加えて、カメラ画像を使った処理なども組み合わせています)

試す内容

今回試すのは、フィルター用シェーダー「createFilterShader()」を使った処理で、「メインキャンバスの描画内容をシェーダーに渡して処理するだけでなく、とオフスクリーンキャンバスの描画をまぜる」というものです。

「createFilterShader()」を使う場合、メインキャンバスの内容はデフォルトで利用できる形(シェーダーの中で tex0 という記載で取得できる形)ですが、オフスクリーンキャンバスもシェーダー内で利用できる形にします。
そして、そのようにしてシェーダーに渡した 2つのキャンバスの内容を、シェーダーの中で扱う処理を試していきます。

書いたプログラム

今回書いたプログラム全体は、以下の通りです。

let pg;
let s;

function setup() {
  let fragSrc = `precision highp float;

  varying vec2 vTexCoord;
  uniform sampler2D tex0;

  uniform sampler2D tex1;

  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
    vec4 color2 = texture2D(tex1, vTexCoord);

    gl_FragColor = vec4(color.rgba + color2.rgba);
  }`;

  createCanvas(400, 300, WEBGL);
  background(0);
  noStroke();
  fill(100, 50, 50);
  rect(-50, -50, 200, 150);

  pg = createGraphics(width, height);
  pg.noStroke();
  pg.fill(100, 150, 200);
  pg.circle(120, 120, 190);

  s = createFilterShader(fragSrc);
  s.setUniform("tex1", pg);

  filter(s);
}

ポイントになる部分

今回のポイントになる部分は、以下です。

  s.setUniform("tex1", pg);

pg = createGraphics(width, height) として作成したオフスクリーンキャンバスを、シェーダーに渡します。

シェーダーでそれを受けとる側は、以下とすれば OK です。

  uniform sampler2D tex1;

あとは、何らかのシェーダー内での処理を実装して、メインキャンバスの内容とオフスクリーンキャンバスの内容を両方使えているかを確認します。
今回は以下のように、2つのキャンバスのピクセルの値を単純に加算する、というシンプルな内容で試しています。

  void main() {
    vec4 color = texture2D(tex0, vTexCoord);
    vec4 color2 = texture2D(tex1, vTexCoord);

    gl_FragColor = vec4(color.rgba + color2.rgba);
  }

実行結果

上記を実行した結果は以下になりました。

image.png

2つのキャンバスで行った描画に関しては、以下のように、メインキャンバスとオフスクリーンキャンバスのそれぞれで、特定の色で図形を描画しています。
そして、それをシェーダーで処理した結果が上に示したとおりなのですが、 blendMode(ADD) を使ったのと同じように加算合成を行った見た目になりました。

  createCanvas(400, 300, WEBGL);
  。。。
  fill(100, 50, 50);
  rect(-50, -50, 200, 150);

  pg = createGraphics(width, height);
  。。。
  pg.fill(100, 150, 200);
  pg.circle(120, 120, 190);
1
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
1
1