Three.js勉強2: シーンの主要要素

# はじめに
以前、[React Three Fiber(R3F)に関する記事](https://qiita.com/skm_bnn/items/9bdca6e2965fe8fa61e5)を投稿しました。ReactではThree.jsを容易に扱えるとの噂で、触ってみましたが、そもそもThree.jsでできることが何なの分からず、環境構築止まりになってしまいました。そこで、本記事ではThree.jsを基礎から学びつつ、備忘録として記事にまとめてみたいと思います。


- [Three.js勉強1: 環境構築](https://qiita.com/skm_bnn/private/fe4c17ac65ce5c4a89db)
- [Three.js勉強1.5: 環境構築(ローカル編)](https://qiita.com/skm_bnn/private/4a9a739ec08a41f2588e)
- [Three.js勉強2: シーンの主要要素](https://qiita.com/skm_bnn/private/32f21e39ed40668041e9)
- [Three.js勉強3: 3Dオブジェクトの描画](https://qiita.com/skm_bnn/private/e0611cfd717b96f7ff98)
- [Three.js勉強4: アニメーションと再レンダリング](https://qiita.com/skm_bnn/private/9bd86ab51a829efc43ef)

# 前回の記事

https://qiita.com/skm_bnn/items/fe4c17ac65ce5c4a89db

# 主要な構成要素
Three.jsでオブジェクトを描画するにあたり次の3つが必要です。

- シーン
- カメラ
- レンダラー

## シーン
[シーングラフ](https://threejs.org/manual/#en/scenegraph)という木構造で3Dシーンを構成します。```Scene```オブジェクトの他にシーングラフの構成要素は、```Object3D```オブジェクトや```Light```オブジェクト、```Mesh```オブジェクトや、```Group```オブジェクトなどがあります。

## カメラ
シーングラフとは独立したオブジェクトです。カメラには、複数の種類があります。

- [PerspectiveCamera](https://threejs.org/docs/#api/en/cameras/PerspectiveCamera)
- [OrthographicCamera](https://threejs.org/docs/#api/en/cameras/OrthographicCamera)
- [CubeCamera](https://threejs.org/docs/#api/en/cameras/CubeCamera)
- [ArrayCamera](https://threejs.org/docs/#api/en/cameras/ArrayCamera)

## レンダラー
Three.jsの主要なオブジェクトとなります。レンダラーにシーンとカメラを渡すことで、3Dシーンを2D画像としてキャンバスにレンダリングします。

# 実装
主要な構成要素であるレンダラーとシーン、カメラをそれぞれ実装していきます。

## シーン
次のコードでシーンオブジェクトのインスタンスを生成します。

```js
const シーン = new THREE.Scene();
```

## カメラ
次のコードで```PerspectiveCamera```という種類のカメラを生成します。

```js
const カメラ = new THREE.PerspectiveCamera( 視野範囲, アスペクト比, 近面, 遠面 );
```
|引数|内容|値の例|
|---|---|---|
|視野範囲|ディスプレイに表示されるシーンの範囲(単位は度)|```75```|
|アスペクト比|画面の比率(横幅/高さ)|```window.innerWidth / window.innerHeight```|
|近面|近面の位置|```0.1```|
|遠面|遠面の位置|```1000```|

### 補足: 近面と遠面
近面と遠面の間にある描画オブジェクトがレンダリングの対象となります。例えば、カメラに対して、近面より近い座標、あるいは遠面より遠い座標にある描画オブジェクトは画面上に表示されません。基本的には表上にある値で問題がないようですが、描画処理が重く感じた時に調整します。

## レンダラー
レンダラーを実装するには次の流れとなります。

1. レンダラーの作成
1. レンダリングするサイズの設定
1. レンダラーをHTMLへ反映

### レンダラーの作成
次のコードでレンダラーオブジェクトのインスタンスを生成します。

```js
const レンダラー = new THREE.WebGLRenderer();
```
### レンダリングするサイズの設定
次のコードで描画する領域の大きさを設定します。

```js
レンダラー.setSize( 横幅, 高さ, 更新スタイル );
```
|引数|内容|値の例|
|---|---|---|
|横幅| 描画する領域の横幅 |```window.innerWidth``` |
|高さ| 描画する領域の高さ | ```window.innerHeight``` |
|更新スタイル| 高解像度にするか否か |```false```|

#### 補足: 更新スタイルについて
第三引数「更新スタイル」はデフォルト引数であり、省略が可能です。その場合は```True```が渡され、高解像度の設定となります。

### レンダラーをHTMLへ反映
次のコードでレンダラーをHTMLへ反映します。

```js
document.body.appendChild( レンダラー.domElement );
```

# ソースコード
次に今回の内容をまとめたソースコードを示します。

```js: main.js
import * as THREE from 'three';

/* シーンの実装 */
const scene = new THREE.Scene();

/* カメラの実装 */
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

/* レンダラーの実装 */
const renderer = new THREE.WebGLRenderer();               // インスタンスの生成
renderer.setSize(window.innerWidth, window.innerHeight);  // サイズの設定
document.body.appendChild(renderer.domElement);           // HTMLへの追加
```

# 動作結果
現在は、描画するオブジェクトを実装していないので何も映っていません。白いページが表示されているだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/18bb0e5a-c890-9d34-5d42-b34eed4aef05.png)

# 次回の記事

https://qiita.com/skm_bnn/items/e0611cfd717b96f7ff98

# 参考
- シーンの作成

https://threejs.org/docs/#manual/en/introduction/Creating-a-scene

- シーングラフ

https://threejs.org/manual/#en/fundamentals