ICS MEDIA - インタラクションデザイン×ウェブテクノロジー

WebGL と JavaScript で学ぶ3D表現

簡単な Three.js のサンプルを試そう

Three.jsはHTMLの3D技術「WebGL」を扱いやすくしたフレームワークです。Three.jsを使えばGPUによる本格的な3D表現をプラグイン無しで作成できます。

▲Three.jsの公式サイト

ライブラリのセットアップから3D画面への表示および直方体の回転までを紹介します。手順通りに進めば、20分くらいで作業が完了できると思います。

まずはHTMLファイルを用意して、次のコードを貼り付けて試してください。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>
  <script>
    // ページの読み込みを待つ
    window.addEventListener('load', 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);
      camera.position.set(0, 0, +1000);

      // 箱を作成
      const geometry = new THREE.BoxGeometry(400, 400, 400);
      const material = new THREE.MeshNormalMaterial();
      const box = new THREE.Mesh(geometry, material);
      scene.add(box);

      tick();

      // 毎フレーム時に実行されるループイベントです
      function tick() {
        box.rotation.y += 0.01;
        renderer.render(scene, camera); // レンダリング

        requestAnimationFrame(tick);
      }
    }
  </script>
</head>
<body>
  <canvas id="myCanvas"></canvas>
</body>
</html>

ブラウザの画面上に単色の直方体が回転します。

ちなみに前提としてThree.jsはWebGL対応のブラウザが必須となりますので、動作確認はFirefoxやChrome、Safari、Edgeなどを使うといいでしょう。

また、WebGLはローカルファイルのセキュリティーの制限があるため、ローカルサーバー上で実行することをオススメします。ローカルサーバーの構築方法がわからなければ、エディターの「Brackets」がボタン一つで実行できるのでオススメです。

ここからは、上記のコードを解説していくので、一つ一つ理解していきましょう。

canvas要素を用意する

Three.jsはHTML5のcanvas要素を利用します。canvas要素はコンテンツを表示する描画エリアとなります。canvas要素には属性としてid(ID値)を最低限設定しておきましょう。

<body>
  <canvas id="myCanvas"></canvas>
</body>

canvas要素の大きさはJavaScriptを使って設定します。

JSライブラリを読み込む

Three.jsはJavaScriptのライブラリですが、このファイルを読み込むことによってはじめてThree.jsが利用できるようになります。

CDN(コンテンツ・デリバリー・ネットワーク)で提供されているURLを使うのが導入にお手軽です。

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>

WebGLの処理はページの読み込みが終わってから実行させます。addEventListener()関数を使ってloadイベントが発生するのを監視させ、ページが読み込み終わったときに実行させたい関数を指定します。この関数init()の中にThree.jsのコードを書いていきます。

<script>
window.addEventListener('load', init);
function init(){
  // 処理
}
</script>

3D表示用のJavaScriptを用意

WebGLのレンダリングをするためのレンダラーを作成します。THREE.WebGLRendererクラスのコンストラクターには引数として、HTMLに配置したcanvas要素を指定し、連携させます。

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

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

renderer.setSize(960, 540);

シーンを作成する

シーンを作成します。シーンとは3D空間のことで、3Dオブジェクトや光源などの置き場となります。

const scene = new THREE.Scene();

カメラを作る

3Dではどの視点から空間を撮影するか、という実装をします。この機能は「視点」や「カメラ」と呼ばれます。

Three.jsではTHREE.PerspectiveCameraクラスのコンストラクターで画角、アスペクト比、描画開始距離、描画終了距離の4つの情報を引数として渡しカメラを作成します。

// new THREE.PerspectiveCamera(画角, アスペクト比
const camera = new THREE.PerspectiveCamera(45, 960 / 540);

立方体を作る

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

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

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

マテリアルは色や質感の情報を持っています。今回はとりあえず箱を表示させたいので、THREE.MeshNormalMaterialという適当なカラーを割り振るマテリアルを生成します。

const material = new THREE.MeshNormalMaterial();

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

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

アニメーション

JavaScriptでアニメーションをさせるには、時間経過で関数を呼び続ける必要があります。そのためには、requestAnimationFrame()というグローバルメソッドを使用します。requestAnimationFrame()は引数として渡された関数を、毎フレーム実行します。

// 初回実行
tick();

function tick() {
  requestAnimationFrame(tick);

  // アニメーション処理をここに書く
}

次に、Three.jsの表示結果を更新する命令を書きます。Three.jsでは自動的に画面が最新に切り替わらないので、明示的に画面が更新されるように命令を書く必要があります。renderer.render()という命令で更新を指示できます。

// 初回実行
tick();

function tick() {
  requestAnimationFrame(tick);

  // アニメーション処理をここに書く

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

アニメーションの処理として、立方体が回転するようにしてみましょう。時間経過で回転するようにrotation.yプロパティの数値を加算しています。

// 初回実行
tick();

function tick() {
  requestAnimationFrame(tick);

  // アニメーション処理をここに書く
  box.rotation.y += 0.01;
  renderer.render(scene, camera); // レンダリング
}

以上がサンプルの解説となります。

Three.jsの基本構造

上記のコードで出現したThree.jsの基本機能について紹介します。

図:Three.jsを構成する基本的なオブジェクトと表示の仕組み
ビュー(HTMLのcanvasタグ)が実際に表示される画面となります。

THREE.Sceneクラス

3Dの空間を表すクラス。3Dのオブジェクトはシーンにadd()メソッドを利用して追加することで表示できます。

THREE.PerspectiveCameraクラス

3D空間を撮影するカメラ。視点を制御するために使用します。3D空間のどの視点で撮影しているのかの情報が必要となります。

THREE.WebGLRendererクラス

3D空間のレンダリングを行います。レンダリングとは、Three.jsで計算した3Dのオブジェクトを画面に表示することです。内部的にはThree.jsがWebGLのAPIを使って、GPUで座標を計算させ画面に表示させています。Three.jsではrequestAnimationFrameのタイミングにあわせて、レンダリングを行うように設定しましょう。

まとめ

3Dと聞くと難しそうと思われがちですが、あっけなく動作したので驚かれた方も多いのではないでしょうか?

次回の記事では、マテリアルやライティングの設定方法を説明します。

次の記事へ