Three.js 事始め#1 - とにかく作ってみる

WebGLをサポートするブラウザは以下で確認できます。

http://caniuse.com/#feat=webgl

アプリケーションのひな形

最初にベースになるHTMLを作っておきます。

<!DOCTYPE html>  
<html>  
<head>  
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Hello Three.js</title>
  <style>
    body{
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
  </style>
</head>  
<body>  
  <div id="app"></div>

  <script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.js"></script>
  <script src="./app.js"></script>
</body>  
</html>  
//
// app.js
//
(function() {

    function init() {
        console.log('init');
    }

    window.addEventListener('load', init, false);

})();

Three.jsのオブジェクトを利用する

初めてのWebGLということで、以下のオブジェクトを利用してグラフィックを描画してみます。

Plane 2次元の矩形
Sphere 3Dの球体
Camera ブラウザ上にレンダリングされたものを見るカメラ
Axes X/Y/Z軸。Xは赤、Yは緑、Zは青の線で表示される
//
// app.js
//
(function() {

    function init() {

        var winW = window.innerWidth;
        var winH = window.innerHeight;

        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, winW / winH, 0.1, 1000);
        var renderer = new THREE.WebGLRenderer();

        renderer.setClearColor(0xEEEEEE);
        renderer.setSize(winW, winH);

        var axes = new THREE.AxisHelper(20);

        scene.add(axes);

        var planeGeometry = new THREE.PlaneBufferGeometry(50, 20, 1, 1);
        var planeMaterial = new THREE.MeshBasicMaterial({
            color: 0xCCCCCC
        });
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);

        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 0;
        plane.position.y = 0;
        plane.position.z = 0;

        scene.add(plane);

        var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
        var sphereMaterial = new THREE.MeshBasicMaterial({
            color: 0x7777ff,
            wireframe: true
        });
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

        sphere.position.x = 0;
        sphere.position.y = 4;
        sphere.position.z = 0;

        scene.add(sphere);

        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        document.getElementById('app')
            .appendChild(renderer.domElement);

        renderer.render(scene, camera);

    }

    window.addEventListener('load', init, false);

})();

ページをロードすると以下の様なグラフィックが表示されればOKです。

コードを読む

まずはこの部分です。

var scene = new THREE.Scene();  
var camera = new THREE.PerspectiveCamera(45, winW / winH, 0.1, 1000);  
var renderer = new THREE.WebGLRenderer();

renderer.setClearColor(0xEEEEEE);  
renderer.setSize(winW, winH);  

Scene、Camera、Rendererオブジェクトを作っているというのが何となくわかります。sceneオブジェクトは画面に描画する全てのモノのコンテナです。Three.Sceneのオブジェクトが無いと何も表示することはできません。次にcameraオブジェクトです。CameraはSceneを描画した時に何が見えるかを定義します。さらにrendererを定義しています。RendererはCameraのアングルを元にSceneがどのように見えるかを計算します。

最後にrendererオブジェクトを設定しています。setClearColor()で背景色、setSize()でSceneのサイズを定義しています。ここまでで、空のSceneを作ったことになります。

空のSceneを作ったので、3D空間に配置するAxis、Plane、Sphereを定義しているのが以下の部分です。

var axes = new THREE.AxisHelper(20);  
scene.add(axes);

// w:50, h:20, 横分割数:1, 縦分割数:1 => 50x20の一枚の平面
var planeGeometry = new THREE.PlaneBufferGeometry(50, 20, 1, 1);  
var planeMaterial = new THREE.MeshBasicMaterial({  
    color: 0xCCCCCC
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);

plane.rotation.x = -0.5 * Math.PI;  
plane.position.x = 0;  
plane.position.y = 0;  
plane.position.z = 0;

scene.add(plane);

// 球の半径:4, 幅分割数:20, 高さ分割数:20の球体
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);  
// 表面をワイヤーフレームにする
var sphereMaterial = new THREE.MeshBasicMaterial({  
    color: 0x7777ff,
    wireframe: true
});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

sphere.position.x = 0;  
sphere.position.y = 4;  
sphere.position.z = 0;

scene.add(sphere);  

軸はTHREE.AxisHelper()のインスタンスをScene.add()するだけで作ることができます。次のPlane、Sphereが実際に3D空間に配置するオブジェクトです。2つに共通する処理として"~Geometry"と"~Material"を作って"Mesh"にし、位置を設定して、Sceneに追加するというようなことをやっていることがわかります。Geometryは形状、Materialは表面、これらを組み合わせたMeshがモノといった意味になります。

最後にCamera位置と、向きを設定し、レンダリングしているのが以下のコードになります。

camera.position.x = -30;  
camera.position.y = 40;  
camera.position.z = 30;  
camera.lookAt(scene.position);

document.getElementById('app')  
    .appendChild(renderer.domElement);

renderer.render(scene, camera);  

camera.lookAt()でSceneの位置(デフォルトの(0,0,0))を指定し、カメラの向きをSceneの中心に向けます。次に描画するDOM要素にrendererが出力するCanvas要素をいれます。最後にrender()でCameraを使用してSceneを描画します。

まとめ

  • Scene/Camera/Rendererオブジェクトを作る
  • オブジェクト = 3D空間上に配置するモノ(Mesh) = 形状(Geometry) + 表面(Material)
  • オブジェクトはSceneに追加する
  • DOMにRenderer.domElement(= Canvas)を子要素として追加して、Renderer.render()で画面を描画する

以上、ひとまず画面に物体を描画する流れをなんとなく理解できました。次回は表面(Material)とライトで体裁を整えます。