Three.jsのほんとに基本だけ

Three.jsについての超初歩的な基本を備忘録として書いてみます。

# Three.jsとは？

Three.jsは、Webブラウザ上で3Dコンテンツを制作できるJavaScriptライブラリです。通常、GLSL（シェーダー言語）を使って3Dを実装するのは大変ですが、Three.jsを利用することで、より簡単に3D空間を構築できます。


## ざっくりのイメージ

3D空間を作るにはシーンと、カメラと、レンダラーが必須。

* シーン（Scene）: 3D空間そのもの。
* カメラ（Camera）: シーンを撮影するための視点。
* レンダラー（Renderer）: カメラで撮影したシーンをブラウザに表示する。

シーン（空間）上に、カメラを配置して、レンダラーが出力する。
図にするとこんなイメージ。
![img-1024x590.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62365/65dbf6b6-1c87-af97-9678-e99f10ac6e88.png)


これらの要素を組み合わせて3D空間を作ります。

```javascript
const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 500); // カメラの位置を設定

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight); // レンダラーのサイズを設定

document.body.appendChild(renderer.domElement); // レンダラーをDOMに追加
```

できました！

<p class="codepen" data-height="405" data-default-tab="result" data-slug-hash="abjoExL" data-user="e2saeki" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/e2saeki/pen/abjoExL">
  Untitled</a> by e2saeki (<a href="https://codepen.io/e2saeki">@e2saeki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


…空間の準備が整いますが、まだ何も配置されていないので「空の3D空間」が映し出されただけの状態です。

## オブジェクトを配置する

ここになにかを配置していきます。
ひとまず基本の箱でも置いてみます。

### 基本のオブジェクト構造

オブジェクトを配置するには、以下の3つが必要です：
* ジオメトリ（Geometry）: オブジェクトの形状
* マテリアル（Material）: オブジェクトの見た目（色や質感など）
* メッシュ（Mesh）: ジオメトリとマテリアルを組み合わせたもの

```javascript
const geometry = new THREE.BoxGeometry(100, 100, 100); // 箱のサイズ
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 緑色のマテリアル
const box = new THREE.Mesh(geometry, material); // メッシュに形状と素材を指定

scene.add(box); // シーンに追加
```


## 照明を追加する

現実世界と同じように、3D空間にも光源が必要です。光を追加しないと、真っ暗な空間にオブジェクトが配置されているだけになります。

```javascript
const light = new THREE.DirectionalLight(0xffffff); // 白色の平行光源
light.position.set(1, 1, 1); // ライトの位置を設定
scene.add(light); // シーンに追加
```
これで箱が照らされるようになります。


## シーンの描画

最後に、作成したシーンをブラウザに描画します。

```javascript
 renderer.render(scene, camera);
```
3Dの空間に箱が置かれたものを作ることができました！
<p class="codepen" data-height="405" data-default-tab="result" data-slug-hash="dyjbdYg" data-user="e2saeki" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/e2saeki/pen/dyjbdYg">
  Untitled</a> by e2saeki (<a href="https://codepen.io/e2saeki">@e2saeki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## アニメーションを追加

ここでひとつ重大な事実…ここのカメラってビデオではないのです。
つまり一枚の静止画しか映し出されません。

でもせっかく３Dだし？色々動かしたいですよね。

### 基本的なアニメーション
Three.jsではrequestAnimationFrameを使用して、フレームごとにシーンを更新します。


```javascript
function animate() {
  requestAnimationFrame(animate); // 毎フレーム自身を呼び出す
  
  box.rotation.x += 0.01; // 箱を回転
  box.rotation.y += 0.01;

  renderer.render(scene, camera); // シーンを描画
}

animate();
```

### GSAPでアニメーション
より高度なアニメーションには、GSAPライブラリを使用するのがおすすめです。たとえば、以下のコードで箱を回転させ続けることができます。

```javascript
gsap.to(box.rotation, { duration: 10, y: Math.PI * 2, x: Math.PI * 2, repeat: -1 });
```

<p class="codepen" data-height="405" data-default-tab="result" data-slug-hash="zYLORqP" data-user="e2saeki" style="height: 405px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/e2saeki/pen/zYLORqP">
  sample02</a> by e2saeki (<a href="https://codepen.io/e2saeki">@e2saeki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



## おまけ:スクロール連動のアニメーション

GSAPを使えば、スクロールトリガーを設定して、スクロールに連動した3Dアニメーションも実現できます。

 ```javascript
gsap.registerPlugin(ScrollTrigger);

ScrollTrigger.create({
  trigger: box,
  start: 'top center',
  end: 'bottom center',
  onUpdate: (self) => {
    box.rotation.y = self.progress * Math.PI * 2; // スクロール量に応じて回転
  },
});
 ```

<p class="codepen" data-height="405" data-default-tab="result" data-slug-hash="QWBLQJv" data-user="e2saeki" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/e2saeki/pen/QWBLQJv">
  sample03</a> by e2saeki (<a href="https://codepen.io/e2saeki">@e2saeki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## まとめ

Three.jsを使うことで、意外と簡単に3D空間を作ることができます。基本的な流れとしては：

* シーン、カメラ、レンダラーを作成する
* オブジェクトやライトを追加する
* アニメーションやインタラクションを実装する

初歩的なまとめですがなにかの参考になれば