three.jsの基礎の基礎：概要から静止オブジェクトの表示方法まで

[three.jsによるHTML5 3Dグラフィックス(上)](http://www.cutt.co.jp/book/978-4-87783-324-4.html)の第2章「three.jsの基礎」を読んで学習したことをまとめてみた。

# three.jsの概要

WebGLを簡単に利用できるようにすることを目的として誕生したライブラリ。
OpenGLをある程度習得した人でないとなかなか敷居が高いWebGLだったが、three.jsによって直感的に実装できるようになった。

単に使いやすいだけではなく、発表当初から多くの協力者によって頻繁に改良が重ねられていて、今後の発展に期待できることも人気の理由のひとつ。

ただし、基本的な仕様はほぼ確定されてきているとはいえ、今後も仕様変更の可能性があるので注意すること。

# three.jsで扱えるレンダラー

three.jsにおけるレンダラーとは、仮想的な3D空間における物体を2Dのディスプレイに適切に描画するためのもの。
HTML5で広がったグラフィックスの描画手段を統一的に取り扱えるように、次のレンダラーが用意されている。
WebGLRendererとCanvasRendererは標準で組み込まれていて、それ以外は外部ライブラリを読み込むことで利用可能となる。
WebGLに対応した環境ではWebGLRendererを利用し、対応していない（かつ、HTML5に対応している）環境ではCanvasRendererを利用するというように使いわけることができる。

### [WebGLRenderer](http://threejs.org/docs/#Reference/Renderers/WebGLRenderer)
その名のとおり、WebGLを扱うレンダラー。

### [WebGLRenderTarget](http://threejs.org/docs/#Reference/Renderers/WebGLRenderTarget)
オフスクリーンレンダリング（バックグラウンドでのレンダリング）を可能にする。
画像処理を行いながら動的にテクスチャを生成したりできる。
オフスクリーンレンダリングについては[wgld.org | WebGL: フレームバッファ](http://wgld.org/d/webgl/w040.html)を参照。

### [CanvasRenderer](http://threejs.org/docs/#Reference/Renderers/CanvasRenderer)
一般的に2Dグラフィックスを描画するときに使用するCanvas2Dで3Dグラフィックスを実現する。WebGLと異なり、CPUで演算を行うため実行速度が遅くなるが、WebGLで実現できることの大半がCanvas2Dでも可能。

### [SVGRenderer](https://github.com/mrdoob/three.js/blob/master/examples/js/renderers/SVGRenderer.js)
ベクトル画像を扱うSVGを用いた3Dグラフィックスを実現する。

### [SoftwareRenderer](https://github.com/mrdoob/three.js/blob/master/examples/js/renderers/SoftwareRenderer.js)
すべての計算をGPU側でなくCPU側で行うソフトウェアレンダリングを実現する。
GPUの制限を受けない分柔軟性はあるが、実行速度が遅くなる。

### [CSS3DRenderer](https://github.com/mrdoob/three.js/blob/master/examples/js/renderers/CSS3DRenderer.js)
HTMLの要素とCSS3で3Dグラフィックスを実現する。
three.jsの演算機能でCSS transformを扱うことができ、WebGLが対応していないモバイル端末でも3Dグラフィックスを簡単に実現できる。

# ダウンロード方法
公式ページ（[three.js - Javascript 3D library](http://threejs.org/)）の左側メニューにある「download」からダウンロードする。

# 静止オブジェクトを表示する

three.jsによる静止オブジェクトの描画には次の手順が必要。

- HTML文書の作成
- レンダラーの生成
- シーンの生成
- カメラの生成
- 描画したいオブジェクトの生成
- レンダリング

WebGLはcanvas要素で確保された領域に描画を行うが、three.jsでは
レンダラーをDOMに配置すれば動的にcanvas要素が生成されるので、わざわざcanvas要素を置く必要はない。

各手順ごとにコードを分割して説明する。

## 1. HTML文書の作成

three.jsと描画処理を行うJavaScriptファイルの読み込みを行い、body要素内に描画する領域をdiv要素で用意する。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>静止オブジェクトの描画</title>
    <style>
      #canvas {
        width: 800px;
        height: 600px;
      }
    </style>
  </head>
  <body>
    <div id="canvas"></div>  <!-- 描画領域のためのdiv要素を配置 -->
    <script type="text/javascript" src="three.jsのパス"></script>  <!-- three.jsの読み込み -->
    <script type="text/javascript" src="描画処理を行うJSファイルのパス"></script>  <!-- 外部ファイルとして描画処理用スクリプトの読み込み -->
  </body>
</html>
```

## 2. レンダラーの生成

描画処理用のJavaScriptファイルを書いていく。
レンダラーの生成はHTMLで指定した領域に描画領域をつくるような感じ。

```js
var renderer;

canvas = document.getElementById('canvas'); // div要素の取得
renderer = new THREE.WebGLRenderer(); // レンダラーの生成
renderer.setSize(canvas.clientWidth, canvas.clientHeight); // レンダラーのサイズをdivのサイズに設定
renderer.setClearColor(0x000000, 1.0); // レンダラーの背景色を黒色（不透過）に設定
canvas.appendChild(renderer.domElement); // div領域にレンダラーを配置
```

## 3. シーンの生成

シーンとは仮想的な3D空間のことで、コードはわずか1行。

```js
var scene = new THREE.Scene(); // シーンの生成 
```

## 4. カメラの生成

3D空間上のオブジェクトを2Dに投影するためのカメラを生成する。
「透視投影」と「正投影」の2種類の方式が用意されている。

- 透視投影：通常の物の見え方がこちら。遠くのものを小さく、手前のものを大きく描画して遠近感を生み出す。
- 正投影：距離によらず見た目の大きさを一定に描画する。

透視投影には`PerspectiveCamera`クラス、正投影には`OrthographicCamera`クラスを使用する。

`PerspectiveCamera`は`fov`（視野角）、`aspect`（縦横比）、`near`（カメラ～視体積手前間の距離）、`far`（カメラ～視体積奥間の距離）の4つのパラメータをもつ。

視体積や視野角がいまいちわからないという方は、[WebGLのカメラを使いこなす！カメラの設定方法と考え方 | Web制作会社スタイル](http://www.hp-stylelink.com/news/2013/11/20131107.php#list02)に図があるので、参考にしてください。

`OrthographicCamera`は`left`、`right`、`top`、`bottom`（いずれもカメラ中心座標からの長さ）、`near`、`far`の6つのパラメータをもつ。

一般的に利用されるのは透視投影のカメラだと思うので、ここでは透視投影の例を示す。

```js
var fov = 45; // 視野角：0～90
var aspect = canvas.clientWidth / canvas.clientHeight; // 縦横比
var near = 1; // 視体積手前までの距離
var far = 1000; // 視体積奥までの距離

var camera = new THREE.PerspectiveCamera(fov, aspect, near, far); // カメラの生成
camera.position.set(100, 100, 100); // カメラ位置の設定
camera.up.set(0, 0, 1); // カメラの上方向ベクトルの設定
camera.lookAt({x: 0, y: 0, z: 0}); // カメラ視野の中心座標の設定
```

書籍では`camera.position = new THREE.Vector3(100, 100, 100);`としてカメラ位置を設定していたが、
2015/10/09現在はVector3を使用した代入ができないようになっているので注意。
（`camera.position.x = 100;`などはできた。）

## 5. 描画したいオブジェクトの生成

仮想3D空間に配置したいオブジェクトをつくる。
いろいろなthree.jsにはジオメトリが用意されているが、例として軸オブジェクトを生成する。
他にどのようなオブジェクトが配置できるのかについては[Three.jsでいろいろな図形を描いてみる | mwSoft](http://www.mwsoft.jp/programming/webgl/geometry.html)が参考になりそう。

軸オブジェクトはx, y, z軸を線で表現する`AxisHelper`クラスを使用して生成する。

```js
var axis = new THREE.AxisHelper(100); // 長さ100の軸オブジェクトを生成
scene.add(axis); // シーンにオブジェクトを追加
```

## 6. レンダリング

canvasに生成したレンダラーにシーンとカメラを与えることで3Dオブジェクトを描画する。

```js
renderer.render(scene, camera);
```

以上の流れさえ理解しておけば、静止オブジェクトはだいたい表示できるはず。
細かいプロパティなどは[リファレンス](http://threejs.org/docs/)を参照。
リファレンスから作例にも飛べて、「こんなこともできるんだ！」という発見もあるので見てみるとなかなか楽しい。

上で例として示したコードはそのまま全部コピペしただけで実行できるはずなので、
全体のコードは割愛する。
（サンプルコードは検索してみるとたくさん出てくるので、そちらを参考にどうぞ。）