p5.js Web Editor で CDN からの Three.jsモジュール版の読み込み（esm.sh から、ダイナミックインポートを利用した形も）

以下の記事でも扱っていた、p5.js Web Editor で JavaScript のモジュールを扱う話です。今回は Three.js の最新版 r16x系でやってみます。

- [【完走賞ゲット-7】p5.js Web Editor で JavaScript のモジュール（ES Modules）を扱う： simplex-noise.js の最新版（4.x）を CDN から import する - Qiita](https://qiita.com/youtoy/items/6f6522e2df781a200b39)
- [p5.js Web Editor で JavaScript のモジュール（ES Modules）を扱う【その2】： simplex-noise.js の CDN からの import でダイナミックインポートを使う - Qiita](https://qiita.com/youtoy/items/838dce76d5be0d44fa14)

## Three.js の CDN からの読み込み
Three.js の CDN からの読み込みは、r159 などの r15x系であれば Scriptタグで読みこむだけで OK です。例えば、unpkg.com から、以下で読みこむことができます。

```html
    <script src="https://unpkg.com/three@0.159.0/build/three.min.js"></script>
```

ちなみに、上記のファイルの冒頭には、以下の処理が書かれています。
Scriptタグで読み込める形は、r15x系ではギリギリ使えるものの、r16x系ではそれに対応したファイルが削除されるということも書いています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/1daff067-20d6-f46c-c6d8-4c4bbbbe6d67.png)

そのため、r16x系を CDN から読み込む場合は、モジュール版の読み込みの対応が必要になります。

## p5.js Web Editor で CDN から読み込む
### 方法1： Scriptタグに type="module" をつける
まず、スタンダードな方法は以下を用いた方法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fa4171d1-1d40-7ed9-581d-f87bb4e33d0c.png)

p5.js Web　Editor の HTML で、sketch.js　を読みこむタグには `type="module"` をつけます。

```html
    <script src="sketch.js" type="module"></script>
```

そして、以下のように `import * as THREE from "https://esm.sh/three@0.161.0";` という書き方で読みこみます。

```javascript
import * as THREE from "https://esm.sh/three@0.161.0";

window.setup = () => {
  createCanvas(500, 400);

  const scene = new THREE.Scene();
  console.log(scene);
};

window.draw = () => {
  background(0);
};
```

Scriptタグに `type="module"` をつけると、p5.js がいつものやり方で対応できなくなるので、windowオブジェクトを使うなどの対応が必要になります。

上記では、過去の記事でも使ったやり方、 `window.setup = () => {...}` と `window.draw = () => {...}` と書く形で対応すれば OK です。

### 方法2： ダイナミックインポート
上記と別のやり方で、過去の記事でも使ったダイナミックインポートを利用してみます。
この方法の場合は、Scriptタグに type="module" をつける対応は不要です。

この方法のバージョンで、テスト用に書いてみたのが以下のプログラムです。

```javascript
let scene;

async function preload() {
  const THREE = await import("https://esm.sh/three@0.161.0");

  scene = new THREE.Scene();
}

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

function draw() {
  background(0);

  if (scene) {
    console.log(scene);
  }
}
```

preload() のところでダイナミックインポートを使って読みこんでいます。
Scriptタグに type="module" をつけてないため、setup() ・ draw() の書き方はいつも通りで問題なく動作します。

また、Scene() を読みこむ場合に、以下のようにピンポイントに指定するやり方もできます。

```javascript
let scene;

async function preload() {
  const { Scene } = await import("https://esm.sh/three@0.161.0");

  scene = new Scene();
}

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

function draw() {
  background(0);

  if (scene) {
    console.log(scene);
  }
}
```

とりあえず、読み込みが行えているかどうかの確認の処理だけという事例ですが、p5.js Web Editor で CDN からの Three.jsモジュール版の読み込みができました。

## 【追記2】 自分がこれを行う意図について（その後）
p5.js と Three.js をなぜ組み合わせるのか、という話について追記をしていたのですが、さらに追記です。

自分が実現したかったことの 1つ、『「[Vanta.js](https://www.vantajs.com/)」というライブラリで用意されているエフェクトのうち、Three.js に依存しているものを、p5.js上に取り込んで p5.js の処理と組み合わせる』というものが、とりあえず意図通りに動いたので、それを動かしている時の様子を掲載してみます。

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

Three.js のエフェクトについて、以下のようにいろいろ楽しそうなものがあります。
一部は p5.js との組み合わせで使えたのですが、中には Three.js の特定の範囲のバージョンに依存したものがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/271cdbd5-f63e-d36a-4c13-2a30c41a30c7.png)

## 【追記】 自分がこれを行う意図について
p5.js と Three.js をなぜ組み合わせるのか、という話について、少し補足を追記します。

用途としては、例えば以下の時に p5.js の 2D/3D描画のキャンバスと、Three.js の 3D描画のキャンバスを両方使って、それらの描画を合成する、というものです。

- p5.js の 3D系の処理だとできない、3D系の踏み込んだ処理を、p5.jsの2D描画と組み合わせる
- 自分が活用したい 3D描画系ライブラリが Three.js との組み合わせ前提になっているが、p5.jsと組み合わせたい

例として、Three.js と p5.js の例ではないですが、Babylon.js の 3D描画と p5.js の 2D描画とを組み合わせた事例で以下がありました。

https://twitter.com/youtoy/status/1750541825318977552

また、p5.js　とそれ以外の描画ライブラリの併用という方向で 3D系ではないですが、p5.js 以外の描画ライブラリでできることを p5.js に組み合わせたい、という話では以下の PixiJS を組み合わせた事例もあります。

https://twitter.com/youtoy/status/1690295402510340096