Three.jsで地球作ってみた。

## はじめに


今回はThreeJSを使って地球を作ってみたのでメモしたいと思います。
実際のオブジェクトがこちらです。

![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2F4xz2hJdi0MGWbiJW?alt=media&token=9db59ffc-fe78-4d3a-8ce4-3a4368fc01f8)


これがHTMLとJavaScriptで書かれていて、身近な言語で作れることを知った時は感動しました！

## そもそもThreeJSとは

- WebGLと呼ばれるコンピューターグラフィックで使われる難しい技術を、簡単かつ直感的に使えるようにするために作られたJavascriptのライブラリ。

- ThreeJSを使えば、HTMLのcanvas要素にJavascriptで3D描画を描画することが出来る。


## ThreeJSの開発で、絶対に必要な3要素。
- シーン（scene）
- カメラ（PerspectiveCameraなど）
- レンダラー(WebGLRendererなど)

シーンとカメラはなんとなくイメージが湧きますが、レンダラーは分からないですよね。。。

レンダラーは何か結論を言いますと、カメラで写したシーンを、ブラウザで見れるように「変換機」の役割をするのがレンダラーです。


カメラとシーンだけですと、ただカメラがシーンを写してるだけで、レンダラーでブラウザで見れるように変換しないと、確認する事ができません。

流れで言いますと。

カメラでシーンを撮影する

↓

レンダラーで変換する

↓

変換された事により、ブラウザで見れるようになる。

この流れが、ThreeJSの必須の流れです。

以上の事を踏まえてソースコードを書いていきたいと思います。

## Three.jsをインポート
```
import * as THREE from "three";
```

## シーン・カメラ・レンダラー作成

まずはシーンから作ります。
```javascript
import * as THREE from "three";
let scene;　//これから使う変数を宣言

// シーンの作成
scene = new THREE.Scene();
```
シーンの作成は１行でOK。

これでWEBブラウザで何が表示されるか確認してみる

![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FgxuGZloFsgW7yzLs?alt=media&token=4ae6a925-9738-435c-9cff-8edb316b406b)


何も表示されません。
WEBブラウザで何かを表示させるにはカメラ・シーン・レンダラーが必要。

ではシーン・カメラ・レンダラーを作ります。
```
let scene, camera, renderer;

//シーン
scene = new THREE.Scene();

//カメラ
camera = new THREE.PerspectiveCamera(
  50,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(0, 0, 500);

// レンダラー
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
```

カメラにはいろいろ種類があるのですが、今回はPerspectiveCameraを使っています。
PerspectiveCameraは下記のように設定する事ができます。

PerspectiveCamera（視野角、アスペクト比、開始距離、終了距離）

レンダラーでは、bodyタグの中でレンダリングするように記述してます。
setSizeにて、画面一杯に表示するようにしてます。

必須な３要素を準備したのでブラウザで確認してみます。

![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FsuSqy0OC6TbHRyOy?alt=media&token=e464b569-223d-4c1e-8d40-cde829a03cff)

真っ黒ですが、レンダラーでブラウザに表示することが出来ました。

![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FMAMut2rYYQjp6jBI?alt=media&token=8ab2d02a-46da-4f7b-8760-2355e105ec40)

デベロッパーツールで確認してみると、bodyタグの中で表示されています。

次はこの黒い画面にオブジェクトを表示するための準備をしたいと思います。

## 準備
オブジェクトをブラウザに表示するには、**ジオメトリとマテリアルをメッシュ化**しないといけません。

- ジオメトリ：骨格・形
- マテリアル：色・質感
- メッシュ化：ジオメトリとマテリアルを組み合わせる

今回はSphereGeometry（球体のジオメトリ）を使いたいと思います。

```
//ジオメトリの作成
let bollGeometry = new THREE.SphereGeometry(100, 64, 32);
//マテリアルを作成
let ballMaterial = new THREE.MeshPhysicalMaterial();
//メッシュ化
let ballMesh = new THREE.Mesh(bollGeometry, ballMaterial);
scene.add(ballMesh);
// レンダリングしてカメラとシーンを追加。
renderer.render(scene, camera);
```

メッシュ化しただけだと表示する事はできないのでレンダリングします。
これで画面を確認してみます。
背景が黒いと分かりにくいので、宇宙の背景を付け足します。

![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FoLYXzgel0zTevGfg?alt=media&token=76613321-18ea-4e56-9f27-cbd00d67bec5)


ライトを当てていないので黒いですが、実際にレンダリングして表示できたことが確認できました。
次はライトを当てていきたいと思います。

```
//平行光源を追加
let directionalLight = new THREE.DirectionalLight(0xffffff, 2);
scene.add(directionalLight);
```
![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FJg1JvaWFfX26SJDt?alt=media&token=a2257ce9-55cf-4769-9dce-8efd90dbf51a)

これでオブジェクトを照らす事ができました。

ライトの位置を調整する事もできます。

```
//平行光源を追加
let directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
```
![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FSu6dQY7GCfkgq8lK?alt=media&token=feeba214-52fc-4f0c-866e-69cdc8d60838)


最後に少し編集したいと思います。

マテリアルを変更
```
//マテリアルを作成
let ballMaterial = new THREE.MeshLambertMaterial({ color: 0x6699ff });
```
![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FCbTQnaapjmHH303S?alt=media&token=c0a804e0-7a5b-4e4b-b3b5-bfcaa3b40848)

青い星っぽくなりました。

ジオメトリを変更
```
let bollGeometry = new THREE.TorusGeometry(100, 64, 32);
```
![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2FsuMHFa7XP6BnHYOC?alt=media&token=0fa46e6d-35e5-4538-bdbc-bb60a66e47d4)

ドーナツ型にする事ができました。

自分で用意したテクスチャーを貼り付ける事もできます。
loadで読み込んで、マテリアルにmap(マッピング)するみたいです。

```
// テクスチャを追加
let textures = new THREE.TextureLoader().load("./textures/earth.jpg");
//ジオメトリの作成
let bollGeometry = new THREE.SphereGeometry(100, 64, 32);
//マテリアルを作成
let ballMaterial = new THREE.MeshPhysicalMaterial({ map: textures });
//メッシュ化
let ballMesh = new THREE.Mesh(bollGeometry, ballMaterial);
scene.add(ballMesh);
```
![image](https://firebasestorage.googleapis.com/v0/b/ciita-c6ea6.appspot.com/o/user%2Fimages%2F4xz2hJdi0MGWbiJW?alt=media&token=9db59ffc-fe78-4d3a-8ce4-3a4368fc01f8)

地球ですね。


ThreeJSについては分からない事だらけですが、これからも勉強して記事投稿させて頂けたらと思います。

いつか3DのWEBサイトとか作れたらな〜

以上です！


最後まで見ていただきありがとうございました。