PixiJS を p5.js のキャンバスの上で統合させる形で使う（環境は p5.js Web Editor を利用）【試行錯誤の途中】

以前、以下の記事に書いていた「p5.js をメインで使いつつ、一部に PixiJS を混ぜ込んで使う」というのと同じようなことをやってみようとした話で、まだ試行錯誤中の部分が残っている状況の話です。

●p5.js Web Editor上で PixiJS の「ノイズ・色彩・ブラーのフィルタ」を組み合わせて使ってみる - Qiita
　https://qiita.com/youtoy/items/1180c80b91064d4e043d

今回の記事では、 `PIXI.Application()` を p5.js のキャンバスに融合させるような形で処理を書いてみることにしました。なお、それをやる際に、考慮する必要がありそうな部分は、以下となります。

- 普通の使い方をすると、PixiJS も p5.js もそれぞれがキャンバスを独自に作るので、それを 1つにまとめるやり方が必要
- PixiJS と p5.js の描画更新を行う管理部分が独立になるため、そこをうまく合わせこむやり方が必要（PixiJS だと `ticker` 、 p5.js だと `draw()` の処理が担当する部分）

## p5.js Web Editor上で PixiJS を扱うための準備
### プレイグラウンドのプログラム
まず始めに、今回のお試しに使うプログラムを選定します。
アニメーションの仕組み（描画更新の仕組み）が入りつつもシンプルなものが良かったので、以下の PixiJS のプレイグラウンドを開いた時に、デフォルトで読み込まれているプログラムを採用することにしました。

この中の `PIXI.Application()` を p5.js のキャンバスに融合させるような書き方にしつつ、p5.js Web Editor上で動かしてみます。

●Pixi Playground
　https://pixiplayground.com/

なお、プレイグラウンドを開いたときに表示される PixiJS用のプログラムは、以下の通りです。

```javascript
/**
* This is the default playground.
* You should see a bunny spinning in the right preview pane.
* Feel free to use this as a starting point for you own playground!
*/

// Create our application instance
var app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);

// Load the bunny texture
app.loader.add('bunny', 'https://pixijs.io/examples/examples/assets/bunny.png')
    .load(startup);

function startup()
{
    var bunny = new PIXI.Sprite(app.loader.resources.bunny.texture);

    // Center the sprite's anchor point
    bunny.anchor.set(0.5);

    // Move the sprite to the center of the screen
    bunny.x = app.renderer.width / 2;
    bunny.y = app.renderer.height / 2;

    app.stage.addChild(bunny);

    // Listen for animate update
    app.ticker.add(function(delta)
    {
        // Rotate mr rabbit clockwise
        bunny.rotation += 0.1 * delta;
    });
}
```

### CDN からライブラリを読み込む
上記のプログラムを p5.js Web Editor上で扱うために、PixiJS のライブラリの読み込みを行います。
やったことの結論から書くと、 [cdnjs上の PixiJS](https://cdnjs.com/libraries/pixi.js) がいくつかある中で、URL に「browser」が含まれるミニファイされたファイルを指定します（これを、p5.js Web Editor の index.html で読み込ませるようにします）。

このライブラリの読み込みを試した流れについて少し補足すると、最初は「[PixiJS の Getting Started に書かれたもの](https://pixijs.io/guides/basics/getting-started.html)で試しました。しかし `PIXI` を扱えないようなメッセージのエラーが出てしまったので、cdnjs上のミニファイされたライブラリ（複数あるもの）の読み込みを試してみました。

そして、URL に browser という文字列が含まれる以下の 1つ目のものを読み込むと、うまく動作したのでそれで進めることにしました。

:::note 
以下は OK だった
:::

```html
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/6.2.2/browser/pixi.min.js"></script>
```

:::note alert
以下の 2つは NG だった
:::

```html
    <script src="https://pixijs.download/release/pixi.min.js"></script>
```

```html
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/6.2.2/cjs/pixi.min.js"></script>
```

## p5.js Web Editor上で PixiJS のプログラムを動かす
### とりあえず版
上で書いていたように、PixiJS のプレイグラウンドでデフォルトで読み込まれるプログラムを動かしてみます。

p5.js Web Editor の sketch.js の内容を、とりあえず以下のようにしました。
プログラムの補足は、この後に書いていきます。

```javascript
let canvas;
let app;

function setup() {
  canvas = createCanvas(400, 400, WEBGL);

  app = new PIXI.Application({
    view: canvas.elt,
    width: width,
    height: height,
    backgroundColor: 0x2c3e50
  });
  app.loader
    .add("bunny", "https://pixijs.io/examples/examples/assets/bunny.png")
    .load(startup);
}

function startup() {
  const bunny = new PIXI.Sprite(app.loader.resources.bunny.texture);

  bunny.anchor.set(0.5);
  bunny.x = app.renderer.width / 2;
  bunny.y = app.renderer.height / 2;
  app.stage.addChild(bunny);

  app.ticker.add(function (delta) {
    bunny.rotation += 0.1 * delta;
  });
}

function draw() {}
```

引用元と大きく異なる部分は、以下の `PIXI.Application()` を使う部分です。

```javascript
var app = new PIXI.Application({
    width: window.innerWidth,
    height: window.innerHeight,
    backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);
```

これを、以下のようにしています。

```javascript
  canvas = createCanvas(400, 400, WEBGL);

  app = new PIXI.Application({
    view: canvas.elt,
    width: width,
    height: height,
    backgroundColor: 0x2c3e50
  });
```

この p5.js のキャンバスを用意する部分に関して、3つ目の引数で「[WEBGL](https://p5js.org/reference/#/p5/WEBGL)」を指定しています。これを書かなかった場合は、デフォルトでは [P2D](https://p5js.org/reference/#/p5/P2D) が指定されたのと同じ状態になりますが、そうすると以下のようなエラーが発生してしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/79faac39-3cc3-71d1-1adc-986d30a8de62.png)
そのため、「WEBGL」の指定が必須になります。

そして、 `PIXI.Application()` の中では `view: canvas.elt` という記載をしています。
これは、[PIXI.Application() のドキュメント](https://pixijs.download/dev/docs/PIXI.Application.html)で以下のように記載されているオプションを使った形です。
![PIXI.Application()のドキュメント](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/317afeb2-3724-a57d-bc71-ddde343b6c17.png)
ここで `view` に指定できるのが `HTMLCanvasElement` だという仕様であるため、 `canvas.elt` を指定しました（ちなみに、 `canvas` そのものを指定すると、これは「[p5.Element](https://p5js.org/reference/#/p5.Element)」を使う形になりうまくいきません）。

それと、幅・高さ・背景色の指定については、「幅と高さは p5.js　のキャンバスのサイズに合わせる形」として、背景色の指定はそのままの値を用いました。

これで、p5.js側で用意したキャンバスを使って、PixiJS の描画ができる状態になりました。

### 少し書きかえ（draw()内での処理も実行）
このあと、いったん p5.js の `draw()` の中で描画に関わるパラメータ更新を管理する方向で試してみようと思いました。書きかえ後のプログラムは以下の通りです。

```javascript
let canvas;
let app, bunny;

function setup() {
  canvas = createCanvas(400, 400, WEBGL);

  app = new PIXI.Application({
    view: canvas.elt,
    width: width,
    height: height,
    backgroundColor: 0x2c3e50,
  });
  app.loader
    .add("bunny", "https://pixijs.io/examples/examples/assets/bunny.png")
    .load(startup);
}

function startup() {
  bunny = new PIXI.Sprite(app.loader.resources.bunny.texture);

  bunny.anchor.set(0.5);
  bunny.x = app.renderer.width / 2;
  bunny.y = app.renderer.height / 2;
  app.stage.addChild(bunny);
}

function draw() {
  if (bunny) {
    bunny.rotation += 0.1;
  }
}
```

大きく変わった部分を補足します。

以下が変更前です。

```javascript
  // 【一部省略】
  app.stage.addChild(bunny);

  app.ticker.add(function (delta) {
    bunny.rotation += 0.1 * delta;
  });
}

function draw() {}
```

変更後は以下で、 `bunny` の回転用のパラメータの更新を `draw()` の中で行うようにした形です。

```javascript
  // 【一部省略】
  app.stage.addChild(bunny);
}

function draw() {
  if (bunny) {
    bunny.rotation += 0.1;
  }
}
```

これで、 PixiJS の描画の更新は元の仕組みにまかせているままですが、 `bunny` の回転用のパラメータの更新は p5.js 側で処理する形になりました。

## 試行錯誤中の部分
あとは、PixiJS の描画のほうの背景を透過にしたり、p5.js の描画関数を使った描画を合わせて使ってみたり、ということをやろうとしたのですが、まだうまく進められていない状況です。

PixiJS での背景透過については、以下の情報を見つけたり、これを元に公式ドキュメントの情報を確認したりしたのですが、うまく透過された状態になっていません（方向性としては、「useContextAlpha」か「backgroundAlpha」のどちらかを使ったり、ということになるのかな）。

●Transparent background · Issue #31 · pixijs/pixijs
　https://github.com/pixijs/pixijs/issues/31

何らか設定などがうまくできてないところがあるかもしれないですが、PixiJS単体での動作を確認してみたり、引き続き試行錯誤を続けていきたいと思います。

公式ドキュメントは、このあたりをもう少し見ていく必要がありそうかな。

●PixiJS API Documentation： 【AbstractRenderer】
　https://pixijs.download/dev/docs/PIXI.AbstractRenderer.html

●PixiJS API Documentation： 【Application】
　https://pixijs.download/dev/docs/PIXI.Application.html

## おわりに
今回、思ったより試行錯誤が必要になった部分が多く、現時点では未完となっています。

しかし、いろいろ PixiJS と ｐ5．ｊｓ を合わせて使う時のポイントになりそうな点や、調査が必要な対象の絞り込みはある程度はできてきた感じになったように思うので、いったん記事を区切ります（分量的にも、分けたほうが後で見返すのがやりやすそうなのもあり）。

## 【追記】 その後の進捗
この記事でうまくいってなかったことが、想定通りの動作になるようにできました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/p5js?src=hash&amp;ref_src=twsrc%5Etfw">#p5js</a> のキャンバス上で、 <a href="https://twitter.com/hashtag/PixiJS?src=hash&amp;ref_src=twsrc%5Etfw">#PixiJS</a> の描画と p5js の描画の両方を扱う処理、うまくいったっぽい！<br><br>中央で画像が回転しているのが PixiJS での描画で、青っぽい四角が動いているのが p5.js による描画で、メインのキャンバスは p5.js の createCanvas() で生成したもののみを用いています。 <a href="https://t.co/p8gsWOMzhc">pic.twitter.com/p8gsWOMzhc</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1505169226700832772?ref_src=twsrc%5Etfw">March 19, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

そして、その話を続編の記事として書きました！

●PixiJS を p5.js の上で使いつつ p5.js の描画も組み合わせる（環境は p5.js Web Editor を利用） - Qiita
　https://qiita.com/youtoy/items/3e73ad0c11d95f60e79c

## 【追記2】 さらにその後
元々やりたかったこととして、p5.jsベースのプログラムの中で PixiJS のフィルタを使う、というものがあり、それもできそうな感じになってきました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【p5.js と PixiJS を混ぜるお試しの続き】<br>ついに p5.js Web Editor上の <a href="https://twitter.com/hashtag/p5js?src=hash&amp;ref_src=twsrc%5Etfw">#p5js</a> をベースにしたプログラムで、 <a href="https://twitter.com/hashtag/PixiJS?src=hash&amp;ref_src=twsrc%5Etfw">#PixiJS</a> のグローフィルタ（PIXI.filters.GlowFilter）を適用する、というのができた！<br><br>キー操作でフィルタの ON/OFF もできるようにしていて、動画ではその切り替えも行っています。 <a href="https://t.co/FhxTUfnKPO">pic.twitter.com/FhxTUfnKPO</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1505462139691343873?ref_src=twsrc%5Etfw">March 20, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【カーソルの座標に合わせてグローフィルタのパラメータを変化させる】<br>p5.js Web Editor上の <a href="https://twitter.com/hashtag/p5js?src=hash&amp;ref_src=twsrc%5Etfw">#p5js</a> ベースのプログラムで、 <a href="https://twitter.com/hashtag/PixiJS?src=hash&amp;ref_src=twsrc%5Etfw">#PixiJS</a> のグローフィルタ（PIXI.filters.GlowFilter）を使う話の続き。<br><br>p5.js の mouseX・mouseY の値によって、グローフィルタの色・光り方の強度が変わるようにしてみた。 <a href="https://t.co/7yARnZXi3d">pic.twitter.com/7yARnZXi3d</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1505699305088503812?ref_src=twsrc%5Etfw">March 21, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>