Agenda

  • WebGLとThree.jsの概要
  • Three.jsを使ってみよう
  • 関連ツール

WebGLとThree.jsの概要

WebGLについて

  • Webページ上で高度なリアルタイム3DCGを実現
    • Canvas タグの webgl コンテキスト
    • API は OpenGL ES 2.0 とほぼ同じ
  • OpenGLと同様にKHRONOSグループが仕様を管理
  • 各ブラウザのサポート状況
    • Google Chrome 9+, Google Chrome for Android 30+
    • Firefox 4+, Firefox for Android 4+
    • そして...

Welcome!

Three.jsとは

  • WebGLが簡単に使えてしまう魔法のライブラリ
  • Mr.doob氏を中心に開発されている
  • オープンソース(MITライセンス)
    https://github.com/mrdoob/three.js/
  • 豊富な採用事例
  • 現在も活発に開発が進められている

WebGLを直接使うのはたいへんです

Three.jsなら!

// シーンの初期化
var scene    = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(500, 500);
renderer.setClearColor(0x000000, 1);
document.body.appendChild(renderer.domElement);

// カメラの作成
var camera = new THREE.PerspectiveCamera(
  30, 500 / 500, 0.1, 1000 );
camera.position.set(0, 0, 6);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

// ライトの作成
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0.577, 0.577, 0.577);
scene.add(light);

var ambient = new THREE.AmbientLight(0x333333);
scene.add(ambient);
// モデルの作成
var geometry = new THREE.SphereGeometry(1, 16, 8);
var material = new THREE.MeshLambertMaterial(
  { color: 0xffffff , ambient: 0xffffff });
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

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

Three.jsを使ってみよう

初期化

<script src="three.min.js"></script>

<script>
var scene    = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(500, 500);
renderer.setClearColor(0x000000, 1);
document.body.appendChild(renderer.domElement);

// これ以降のコード...
</script>
  • three.min.jsは↓でダウンロードできます。
    http://threejs.org/build/three.min.js
  • THREE.Scene : 描画するシーンを構成するすべてを管理するオブジェクト
  • THREE.WebGLRenderer : WebGLを使用してシーンを描画するレンダラ

カメラの作成

var camera = new THREE.PerspectiveCamera(15, 500 / 500, 0.1, 1000 );
camera.position.set(0, 0, 8);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);
  • THREE.PerspectiveCameraは遠近法による描画を行う
    引数は以下のとおり
    • 視野角(値が小さいと望遠レンズに、大きいと広角レンズになる)
    • 画面のアスペクト比(画面の横幅を高さで割った値)
    • 手前のクリップ距離(この値より近い物体は描画されない)
    • 奥のクリップ距離(この値より遠い物体は描画されない)
  • camera.positionにカメラを配置する座標を指定
  • camera.lokAt()でカメラの注視点(画面の中心になる座標)を指定

ライトの作成

var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0.577, 0.577, 0.577);
scene.add(light);

var ambient = new THREE.AmbientLight(0x333333);
scene.add(ambient);
  • THREE.DirectionalLightは、太陽光のような平行光源。
    • 引数はライトの色を16進数のカラーコードで指定。
  • THREE.AmbientLightは、シーン全体を一様に照らすライト。
    • これがないと、ライトの当たっていない部分が真っ黒になる。

モデルの作成

var geometry = new THREE.SphereGeometry(1, 32, 16);
var material = new THREE.MeshPhongMaterial(
  { color: 0xffffff , ambient: 0xffffff });
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
  • THREE.SphereGeometryで球形を生成する。
    • 引数は半径、経度方向の分割数、緯度方向の分割数。
  • THREE.MeshPhongMaterialで表面の色などを指定
  • THREE.Meshは、実際に画面に表示される物体を表現する。
  • 同じ形を複数表示したい場合は、GeometryとMaterialを使いまわして、Meshのみを表示する数だけ生成する。

レンダリング

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
};
render();
  • THREE.WebGLRendererのrender()を呼ぶだけで描画される。
  • Canvas APIと同様、アニメーションをする場合は自分でループを回す。
  • Tree.jsにはクロスブラウザなrequestAnimationFrame()が実装されているので、それを利用する。

実行結果

テクスチャを貼る

var material = new THREE.MeshPhongMaterial(
  { color: 0xffffff , ambient: 0xffffff,
    map: THREE.ImageUtils.loadTexture('earth.jpg') });
  • マテリアルにmapの指定を追加するだけ!

実行結果

アニメーションする

function render() {
  requestAnimationFrame(render);
  mesh.rotation.y = +new Date * 0.0003;
  renderer.render(scene, camera);
};
render();
  • meshのpositionやrotationを少しずつ変化させる。
  • requestAnimationFrame()の間隔は一定ではないので、実時間をもとに状態を計算する。

実行結果

バンプマッピング(細かい凹凸)

var texture = THREE.ImageUtils.loadTexture('earth.jpg');
var material = new THREE.MeshPhongMaterial(
  { color: 0xffffff , ambient: 0xffffff,
    specular: 0xcccccc, shininess:50,
    map: texture, bumpMap:texture, bumpScale: 0.05 });
  • bumpMapパラメータに高低を色の明るさで表現した画像を指定する。
    • 上記のようにカラーテクスチャと同じでも、それっぽく見えたりする。
  • bumpScaleの値で高低差を調整する(値が大きいほど凹凸も大きくなる)。
  • specular(ハイライト)も指定したほうが効果がわかりやすい。

実行結果

環境マッピング(周りの風景の映り込み)

// キューブマップの6面のURLを配列に格納
var urls = [1, 2, 3, 4, 5, 6].map(function(n) {
  return n + '.jpg';
});

// マテリアルを作成
var material = new THREE.MeshPhongMaterial(
  { color: 0xffffff , ambient: 0xffffff, specular: 0xcccccc, shininess:50,
    bumpMap: THREE.ImageUtils.loadTexture('lib/earth.jpg'), bumpScale: 0.01,
    envMap: THREE.ImageUtils.loadTextureCube(urls), reflectivity: 1.0 });
  • 上下左右前後の6方向の風景を描いた6つの画像を用意する。
  • THREE.ImageUtils.loadTextureCube()で読み込み、envMapに指定。
  • reflectivity で反射率を指定。
  • バンプマッピングとの併用が効果的。

風景画像(キューブマップ)

  • シーンを包む巨大な立方体を想定し、
    その各面にテクスチャを貼る
  • この立方体を周囲の風景と考えて、
    物体上にうまく貼り付けることで、
    映り込みを表現する
  • 面倒な計算はThree.jsがやるので、
    必要なのはテクスチャ画像の指定だけ ;)

実行結果

その他の機能

関連ツール

WebGL Inspector

three.js editor

Clara.io

Shader Editor (Firefox 27+)

GLSL Sandbox

Three.js 使ってみてください!