p5.js のフィルター用シェーダー「createFilterShader()」で作成した描画を 3Dオブジェクトのテクスチャとして用いる

## はじめに
この記事は、以下のように過去に記事を書いてきている「p5.js の createFilterShader() を使ったカスタムシェーダー」の話です。

●「シェーダー user:youtoy」の検索結果 - Qiita
　https://qiita.com/search?q=%E3%82%B7%E3%82%A7%E3%83%BC%E3%83%80%E3%83%BC%20user%3Ayoutoy&sort=created

いろいろ試している中での話で、今回は 3Dオブジェクトのテクスチャに関連した話になります。

## 従来のやり方
「カスタムシェーダーでの描画を 3Dオブジェクトのテクスチャに用いる」という内容は、p5.js公式のサンプルの中にもあります。

具体的には以下のページなどで説明されているもので、頂点シェーダーとフラグメントシェーダーの両方を用意する形です。

●examples | p5.js
　https://p5js.org/examples/3d-shader-as-a-texture.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e8e7c316-b233-0f02-1b15-6686c1e40abe.png)

## 「createFilterShader()」を用いた方法
自分が行ったものは、フラグメントシェーダーのみを「createFilterShader()」を用いて用意する方法です。

シェーダーの部分は、グラデーションを描画するシンプルなものにして試しました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/ftQkkVzToCc?si=W-Q_-GKEv6hoEJ2-" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

### 実装したプログラム
実装したプログラムは以下のとおりです。

```javascript
let s, pg;
let theta = 0;

function setup() {
  createCanvas(550, 400, WEBGL);
  noStroke();

  pg = createGraphics(400, 400, WEBGL);
  pg.pixelDensity(1);

  s = pg.createFilterShader(fragSrc);
}

function draw() {
  s.setUniform("time", millis() / 1500);

  pg.filter(s);

  background(0);
  texture(pg);

  translate(-width * 0.2, 0, 0);
  push();
  rotateZ(theta * 0.05);
  rotateX(theta * 0.15);
  rotateY(theta * 0.1);
  theta += 0.08;
  sphere(width * 0.2, 23, 23);
  pop();

  rect(width * 0.3, -height * 0.2, width * 0.3, width * 0.3);
}

const fragSrc = `#version 300 es
  precision mediump float;

  in vec2 vTexCoord;
  out vec4 outColor;

  void main() {
    vec3 color1 = vec3(0.9, 0.1, 0.8); // magenta
    vec3 color2 = vec3(0.1, 0.8, 0.9); // cyan
    float mask = vTexCoord.x;
  
    vec3 gradient = mix(color1, color2, mask);
    outColor = vec4(gradient, 1.0 );
  }`;
```

#### カスタムシェーダーでのグラデーション
カスタムシェーダーでグラデーションを描画している部分は、以下に掲載されたサンプルを用いています。

●aferriss/p5jsShaderExamples: A collection of heavily commented WebGL shaders created with p5.js and GLSL
　https://github.com/aferriss/p5jsShaderExamples

●p5jsShaderExamples/2_texture-coordinates/2-3_gradient/texcoord.frag at gh-pages · aferriss/p5jsShaderExamples
　https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/2_texture-coordinates/2-3_gradient/texcoord.frag

#### p5.js でカスタムシェーダーを扱う部分
p5.js でカスタムシェーダーを扱う部分は、以下の記事でも書いた内容を使っています。

●p5.js のフィルター用シェーダー「createFilterShader()」で WebGL 2.0（GLSL ES 3.0）を使う ＋ 色・座標情報に関わる書き方を WebGL 2.0対応にする - Qiita
　https://qiita.com/youtoy/items/8b22073f2666ac0c8a3e

#### シェーダーの描画をテクスチャとして使う部分
シェーダーによる描画内容をテクスチャとして使う部分は、[上でも掲載していた公式サンプル](https://p5js.org/examples/3d-shader-as-a-texture.html)をベースにしています。

公式サンプルは、頂点シェーダーとフラグメントシェーダーを用意して読みこむという形だったので、その部分は「createFilterShader()」を用いた方法に置きかえています。

これらを組み合わせて、3Dオブジェクトのテクスチャにシェーダーを使った描画を用いることができました。

### シェーダーの描画でアニメーションを用いる
テクスチャに使うシェーダーの描画は、静止画的なものだけでなく、アニメーションするものも利用可能です。

例えば、以下のような描画を行うこともできます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/ldLV8l8oPK4?si=3GGlCCnTpHqXVcF3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>