p5.js のフィルター用シェーダー「createFilterShader()」で座標・色情報・ベクトルを扱う処理：WebGL 2.0（GLSL ES 3.0）

この記事は、以下の記事などを書いた際に扱った p5.js でシェーダーを扱う話に関連したものです。

●p5.js でのシェーダーを使った描画に WebGL 2.0（GLSL ES 3.0）を使う - Qiita
　https://qiita.com/youtoy/items/af009f7401fd3ce861dd

●p5.js でのシェーダーを使った描画に WebGL 2.0（GLSL ES 3.0）を使う 〜その3：JavaScript側から時間の情報を渡す、createFilterShader() を併用〜 - Qiita
　https://qiita.com/youtoy/items/f3a84a71d1f4fc8f2259

今回、WebGL 2.0（GLSL ES 3.0）と p5.js のフィルター用シェーダー「createFilterShader()」を組み合わせたものについて、シンプルなサンプルを作ってみという内容になります。
シンプルな内容と書いているのは、座標・色情報・ベクトルを扱う処理のシンプルな事例という感じです。

## サンプル
まずは実装した内容と、出力を掲載します。

### コード

```javascript
let s;

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

  s = createFilterShader(fragSrc);
}

function draw() {
  background(0);

  fill(150, 200, 230);
  rect(-200, -100, 400, 200);

  filter(s);
}

let fragSrc = `#version 300 es
  precision mediump float;
  
  in vec2 vTexCoord;
  uniform sampler2D tex0;
  out vec4 outColor;

  void main() {
    vec4 color = texture(tex0, vTexCoord);

    if(vTexCoord.x < 0.2) {
      outColor = color + vec4(vec3(0.2), -0.2);
    } else if(vTexCoord.x < 0.7) {
      outColor = color;
    } else {
      outColor = color * 1.2;
    }
  }`;
```

### 出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/293e1ec6-4cc6-16cf-d824-06cd5fe2d367.png)

### 補足
シェーダーを適用していない場合、以下の見た目になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0b273d54-d929-bbec-0241-cc57f1f0820d.png)

元のコードの、以下の部分で描画される内容です。

```javascript
function setup() {
  createCanvas(500, 400, WEBGL);
  noStroke();
}

function draw() {
  background(0);

  fill(150, 200, 230);
  rect(-200, -100, 400, 200);

  filter(s);
}
```

単純に、背景が黒いキャンバス上に、青系の色で塗りつぶされた矩形が描画されたものです。

これに対して、上の例ではシェーダーによる処理を行っています。

#### 座標・色情報・ベクトルを扱う処理
シェーダーの処理の中で、座標・色情報・ベクトルを扱っているメインの処理部分は以下です。

```c++
    if(vTexCoord.x < 0.2) {
      outColor = color + vec4(vec3(0.2), -0.2);
    } else if(vTexCoord.x < 0.7) {
      outColor = color;
    } else {
      outColor = color * 1.2;
    }
```

color は `vec4 color = texture(tex0, vTexCoord)` としているので、4次元のベクトルです。その中身は、キャンバス上の特定の座標の色情報（RGBA）です。
その値の範囲については、キャンバス側では 0 から 255 までの値だったものが、シェーダーの側では 0 から 1 までの値に正規化されています。

vTexCoord は `in vec2 vTexCoord` としていますが、2次元ベクトルで座標情報です。元のキャンバス上での xy座標そのものではなく、正規化した値です（値のとる範囲は 0 から 1）。

ここでは、x座標が以下のどれになｆるかによって、色を変化させる処理を行っています（上で書いたとおり、vTexCoord.x のとる範囲は 0 から 1 です）。

- vTexCoord.x < 0.2
- vTexCoord.x < 0.7
- それ以外

上記の条件によって、色をどのようにしているかは以下のとおりです。

- color + vec4(vec3(0.2), -0.2) ← RGB の値は 0.2 を足して、A(透明度) は 0.2 を減算
- color ← 色は変化なし
- color * 1.2 ← RGBA の全てを 1.2倍にしているため、色が明るくなる

上記の計算で使っている記法は、[「WebGL2の基本」のページ](https://webgl2fundamentals.org/webgl/lessons/ja/)の以下などデモ説明されているものです。

●WebGLシェーダーとGLSL
　https://webgl2fundamentals.org/webgl/lessons/ja/webgl-shaders-and-glsl.html

このような感じで、キャンバス側がもつ情報のうち「位置座標・色情報」を使ったシェーダーの処理が行えます。

## 余談
上記の[「WebGL2の基本」のページ](https://webgl2fundamentals.org/webgl/lessons/ja/)を見ている中で、以下の PDF「OpenGL ES 3.0リファレンスカード」が気になりました。

https://www.khronos.org/files/opengles3-quick-reference-card.pdf

情報が凝縮されたシートのようなので、後で見てみようと思います。

あと、前に見たことがあったようにも思うのですが、あらためて以下なども見なおしておきたいと思いました。

●WebGL2の新機能
　https://webgl2fundamentals.org/webgl/lessons/ja/webgl2-whats-new.html