コードを書いてみよう!

今回は、以下のような立方体を表示する40行程度の簡単なJavaScriptを書いていきます。サンプルコードもGitHubにアップしているので参考ください。

※このデモはthree.js(r88)で作成しています。

1. レンダラーを作る

WebGLのレンダリングをするためのレンダラーを作成します。引数にはHTMLコード上に記載したcanvas要素の参照を渡します。

const renderer = new THREE.WebGLRenderer({
  canvas: document.querySelector('#myCanvas')
});

デフォルトではレンダラーのサイズが小さいため、setSize()メソッドでサイズを設定します。今回のデモでは幅960px、高さ540pxを設定しています。

renderer.setSize(width, height);

スマホでも綺麗に見えるように、デバイスピクセル比も設定しておきましょう。これを設定しないとスマホだとぼやけて表示されます。

renderer.setPixelRatio(window.devicePixelRatio);

2. シーンを作る

シーンを作成します。シーンはオブジェクトや光源などの置き場です。

const scene = new THREE.Scene();

3. カメラを作る

Three.jsではカメラを作成し、その視点から見えるものがレンダラーを介してcanvasへ描画されます。

concept
THREE.PerspectiveCameraに画角、アスペクト比、描画開始距離、描画終了距離の4つの情報を引数として渡しカメラを作成します。

// new THREE.PerspectiveCamera(画角, アスペクト比, 描画開始距離, 描画終了距離)
const camera = new THREE.PerspectiveCamera(45, 800 / 600, 1, 10000);

4. 立方体を作る

立方体はメッシュという表示オブジェクトを使用して作成します。メッシュを作るには、ジオメトリ(形状)とマテリアル(素材)を用意する必要があります。

ジオメトリは頂点情報や面情報を持っています。Three.jsにはさまざまなジオメトリが用意されていますが、今回は立方体や直方体のような箱状の形状を生成するためのBoxGeometryを使用します。

// new THREE.BoxGeometry(幅, 高さ, 奥行き)
const geometry = new THREE.BoxGeometry(500, 500, 500);

マテリアルは色や質感の情報を持っています。今回は青色の箱を表示させたいので、以下のようにマテリアルを生成します。

const material = new THREE.MeshStandardMaterial({ color: 0x0000FF });

作成したジオメトリとマテリアルを使って、メッシュを作ります。作成したメッシュをシーンに追加しましょう。

// new THREE.Mesh(ジオメトリ,マテリアル)
const box = new THREE.Mesh(geometry, material);
// シーンに追加
scene.add(box);

5. ライトを作る

このままでは真っ暗なのでライトを作成します。

// new THREE.DirectionalLight(色)
const light = new THREE.DirectionalLight(0xffffff);
light.intensity = 2; // 光の強さを倍に
// シーンに追加
scene.add(light);

DirectionalLightは平行光源を意味します。平行光源は太陽光のように一定方向から差し込む光です。ライトもシーンに追加することで反映されます。
光源が斜めから差し込むように位置も変更しておきましょう。

// ライトの位置を変更
light.position.set(1, 1, 1);

6. 描画する

最後はレンダリングです。renderer.render()メソッドに、先程作成したシーンとカメラを引数に渡すことで初めてcanvas上に描かれます。

renderer.render(scene, camera);

index.jsの内容が以下のようになっていれば大丈夫です。実行して確認してみましょう。

window.addEventListener('DOMContentLoaded', init);

function init() {
  const width = 960;
  const height = 540;

  // レンダラーを作成
  // レンダラーを作成
  const renderer = new THREE.WebGLRenderer({
    canvas: document.querySelector('#myCanvas')
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);

  // シーンを作成
  const scene = new THREE.Scene();

  // カメラを作成
  const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
  camera.position.set(0, 0, +1000);

  // 箱を作成
  const geometry = new THREE.BoxGeometry(500, 500, 500);
  const material = new THREE.MeshStandardMaterial({color: 0x0000FF});
  const box = new THREE.Mesh(geometry, material);
  scene.add(box);

  // 平行光源
  const directionalLight = new THREE.DirectionalLight(0xFFFFFF);
  directionalLight.position.set(1, 1, 1);
  // シーンに追加
  scene.add(directionalLight);

  // 初回実行
  renderer.render(scene, camera);
}

次の画像ように表示されていると思います。

render

7. アニメーション

renderer.render()を一度しただけでは、canvasに一度描かれただけなので更新はされません。アニメーションをさせるには、パラパラアニメのようにコマ送りにする必要があります。そのためには、requestAnimationFrame()というグローバルメソッドを使用します。requestAnimationFrame()は引数として渡された関数を、毎フレーム実行します。init()の最後を下のように書き換えてみましょう。

// 初回実行
tick();

function tick() {
  requestAnimationFrame(tick);

  // 箱を回転させる
  box.rotation.x += 0.01;
  box.rotation.y += 0.01;

  // レンダリング
  renderer.render(scene, camera);
}

実行結果を見ると立方体が回転しているはずです。Three.jsでのアニメーションはこうして行います。

animation

完成したJavaScriptのコードは次のようになります。

window.addEventListener('DOMContentLoaded', init);

function init() {
  const width = 960;
  const height = 540;

  // レンダラーを作成
  const renderer = new THREE.WebGLRenderer({
    canvas: document.querySelector('#myCanvas')
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height);

  // シーンを作成
  const scene = new THREE.Scene();

  // カメラを作成
  const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
  camera.position.set(0, 0, +1000);

  // 箱を作成
  const geometry = new THREE.BoxGeometry(500, 500, 500);
  const material = new THREE.MeshStandardMaterial({color: 0x0000FF});
  const box = new THREE.Mesh(geometry, material);
  scene.add(box);

  // 平行光源
  const light = new THREE.DirectionalLight(0xFFFFFF);
  light.intensity = 2; // 光の強さを倍に
  light.position.set(1, 1, 1);
  // シーンに追加
  scene.add(light);

  // 初回実行
  tick();

  function tick() {
    requestAnimationFrame(tick);

    // 箱を回転させる
    box.rotation.x += 0.01;
    box.rotation.y += 0.01;

    // レンダリング
    renderer.render(scene, camera);
  }
}

最後に

立方体を表示できましたが、これだけではコンテンツとして物足りません。冒頭で紹介したサイトのようにコンテンツとして成立させるためには、さらにThree.jsを習得する必要があります。私の周りでThree.jsを触ってみたものの、「次に何を勉強したらいいのかわからない」という声をよく聞きます。

・・・それもそのはず。Three.jsはさまざまな使い方ができるため学ぶべき分野は多岐にわたるからです。そこで、Three.jsを学習するにあたり押さえておくべきポイントや方向性を図にまとめました。

diagram

さまざまな領域を幅広く勉強したり、専門領域に特化して学ぶのも、人それぞれだと思います。まずは興味のある分野から、ステップアップしてみてはいかがでしょうか? さらに勉強にするにはICS MEDIAでは「Three.js入門サイト」で網羅的にまとめているので参照ください。