three.js超入門 第0回 3Dコンピュータグラフィックスの基礎

# 概要
この記事では「three.js超入門」と題して、three.jsの基礎からシェーダーの利用までをやっていきます。
ターゲットは主に「canvas表現を触ったことがないフロントエンドエンジニア」を想定しているので、jsの構文などの説明は省略しています。
three.jsのバージョンは執筆時点で最新の[r98](https://github.com/mrdoob/three.js/releases/tag/r98)を使用します。

three.js超入門 第0回 3Dコンピュータグラフィックスの基礎
[three.js超入門 第1回 レンダリングまでの流れ](https://qiita.com/watabo_shi/items/bf9bcd4569b6d480c608)
[three.js超入門 第2回 アニメーションと時間ベースでの制御](https://qiita.com/watabo_shi/items/1c3c50429279eedec04e)
[three.js超入門 第3回 マウスやスクロールでのインタラクション](https://qiita.com/watabo_shi/items/0811d03390c18e46be86)
[three.js超入門 第4回 getBoundingClientRect()を使ったDOM要素との連携](https://qiita.com/watabo_shi/items/9ab12f62434a1e858226#_reference-a437d85928b89c9bb5e5)
[three.js超入門 第5回 シェーダー(GLSL)の基礎](https://qiita.com/watabo_shi/items/7325948db5c07f6fe9c7)
[three.js超入門 第6回 ShaderMaterialでメッシュを変形、着色する](https://qiita.com/watabo_shi/items/c0d4ef11cba6f21189ed)
[three.js超入門 第7回 シェーダーに変数を渡す](https://qiita.com/watabo_shi/items/1b48ca54a9034f3614d8)
[three.js超入門 第8回 シェーダーをインタラクティブに動かす](https://qiita.com/watabo_shi/items/39d21d53ca16541fd498)
[three.js超入門 第9回 シェーダーでテクスチャにエフェクトをかける](https://qiita.com/watabo_shi/items/2fc671f2147e799787f9)

[リポジトリ](https://github.com/watab0shi/threejs-workshop)

今回はコードを書く前の準備段階として「そもそも3Dコンピュータグラフィックスとは何なのか？」「どういう仕組み・構造で成り立っているのか？」を書いていきます。（コードは次回から出てきます）
three.jsからは少し脱線しますが、WebGL及びOpenGLの基礎を最初に把握しておくことでthree.jsがどこを簡略化して書きやすくしているのかを理解しやすくなると思います。

# 3Dコンピュータグラフィックスとは？
>コンピュータの演算によって3次元空間内の仮想的な立体物を2次元である平面上の情報に変換することで奥行き感（立体感）のある画像を作る手法である。（[Wikipedia](https://ja.wikipedia.org/wiki/3%E6%AC%A1%E5%85%83%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9)から引用）

そもそも映像を表示させるディスプレイやスクリーンが平面なので、行列演算を用いて空間を歪めるなどして平面上に擬似的に三次元空間を表現しています。いわばだまし絵のような感じです。
[このサイト](http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-3-matrices/#%E5%B0%84%E5%BD%B1%E8%A1%8C%E5%88%97)下部の射影変換後の図（青い立方体が歪んでいるやつ）がわかりやすいです。
（とは言っても上記のような行列演算などはライブラリ側でやってくれるので、意識する必要はありません）

## レンダリング
CGを描画することを「レンダリング」といい、レンダリングするためのソフトウェアや仕組みのことを「レンダラー」といいます。

### ラスタ化処理
レンダリングの過程で、プログラムで扱う図形（頂点）データからスクリーンに表示するための画像（画素）データに変換することを「ラスタ化処理」といいます。
IllustratorとPhotoshopを想像するとわかりやすいですね。
（いまは頭の端に置いておけばいい知識ですが、シェーダーを触るときにまた出てきます）
![DQ2P8qcUMAE3VK7.jpg](https://qiita-image-store.s3.amazonaws.com/0/86966/08cee1cd-d153-b445-1571-da82fb40b0b8.jpeg)
（画像は[床井先生のTwitter](https://twitter.com/tokoik/status/940566212118847490/photo/1)から引用）

# 構成要素
3DCGは大きく分けて「モデル」「カメラ」「ライト」の3つから構成されます。

## モデル
形状、色、質感などが設定されたポリゴンのまとまりのことを「モデル」と言います。
MayaやBlenderなどの3DCGソフトで作り込んだ3Dモデルを読み込んだり、プログラムで動的に生成することもできます。
[![スクリーンショット 2018-11-07 12.15.12.png](https://qiita-image-store.s3.amazonaws.com/0/86966/41d35eb2-5182-6cd1-e2b6-312017c3e09d.png)
](https://threejs.org/examples/#webgl_animation_skinning_morph)

### ポリゴン△
3つの頂点から成る三角形のことを「ポリゴン」と呼びます。
ゲームなどでよく聞く「ハイポリ」「ローポリ」という言葉は、この三角形の数の多さを表しています。
3DCGプログラミングでは、このポリゴンを構成する最小要素である「頂点」を制御することで3Dモデルを動的に生成します。
![スクリーンショット 2018-11-07 12.59.24.png](https://qiita-image-store.s3.amazonaws.com/0/86966/a0c0bd30-319c-9c34-7836-5d0b24fefe9e.png)


## カメラ🎥
モデルをカメラで撮影することで、はじめてスクリーンに表示することができます。
カメラの位置や方向、画角の設定によって構図を変更します。
右側のオレンジ色の四角錐がカメラの撮影範囲で、その範囲を撮影したものが左側の画になります。
[![スクリーンショット 2018-11-07 12.39.47.png](https://qiita-image-store.s3.amazonaws.com/0/86966/5bbd3711-0997-1580-3a73-58aa91741f38.png)](https://threejs.org/examples/#webgl_camera)

## ライト💡
モデルとの距離やライトの種類、方向などによってモデルに反射や陰影を表現します。
ベタ塗り表現の場合は使用しません。
[![スクリーンショット 2018-11-07 12.50.42.png](https://qiita-image-store.s3.amazonaws.com/0/86966/ff5a5b51-9766-8425-b1db-7ec540a729f2.png)](https://threejs.org/examples/#webgl_lights_physical)

#頂点バッファ
3DCGプログラミングでは、モデルの情報をそれぞれ「頂点バッファ」と呼ばれる配列に格納します。
それぞれの頂点に対していくつかのデータを設定することができます。
下記の他にも、モデルにテクスチャを貼る際に使用するUV（テクスチャ）座標や、頂点ごとに任意のデータを持たせることも可能です。

※以下で示すサンプルコードは、ローレベルな書き方の例です。three.jsではもっと簡単に書くことができます。

#### Position(座標)
頂点がいまどこにあるのかを（X,Y,Z）で表します。

```javascript
const posisions = [
  x1, y1, z1,// 頂点1の座標 ( X, Y, Z )
  x2, y2, z2,// 頂点2の座標
  x3, y3, z3,// 頂点3の座標
  ...
];
```

#### Color（色）
頂点ごとに色（R,G,B,A）が設定できます。

```javascript
const colors = [
  r1, g1, b1, a1,// 頂点1の色 ( R, G, B, A )
  r2, g2, b2, a2,// 頂点2の色
  r3, g3, b3, a3,// 頂点3の色
  ...
];
```

#### Normal（法線）
この頂点が構成しているポリゴンの面の方向ベクトル（X,Y,Z）を表します。
「面の方向ベクトル」と聞いても理解しにくいとおもいますが、ざっくり言うと、ポリゴンの表がどっちを向いているかの情報です。
ライティングを行う際に使用します。
画像の赤線部が法線です。
[![スクリーンショット 2018-11-07 12.58.49.png](https://qiita-image-store.s3.amazonaws.com/0/86966/2298f0d2-5f00-8cdd-229a-57ecac30ad14.png)
](https://threejs.org/examples/#webgl_geometry_normals)

```javascript
const normals = [
  x1, y1, z1,// 頂点1の法線 ( X, Y, Z )
  x2, y2, z2,// 頂点2の法線
  x3, y3, z3,// 頂点3の法線
  ...
];
```