典型的な3Dゲームのシーン――どんなにシンプルなものでも――には、標準的な項目、すなわち座標に配置された物体、それを見るカメラ、より良い見た目を作る照明と質感の設定、生き生きとしたアニメーションなどが含まれているでしょう。Three.js は他の3Dライブラリと同じように、一般的な機能を迅速に実装するための組み込み関数を提供します。この記事では、開発環境の設定や必要なHTML構造、3つの基本的なオブジェクトの構築や初歩的なデモの制作方法など、Three を使用する上での基本的なことがらを解説します。

Note: 私たちは Three を有名な WebGLライブラリの1つであり、簡単に使い始められるという理由で選びました。Three が他のWebGLライブラリと比べて優秀だというつもりはありません。CopperLicht, GLGE, OSG.js, O3D,その他のあなたが使いやすい物を試すと良いでしょう。

環境構築

あなたがThree.jsで開発を始める上で、必要なものはあまりありません。少なくとも、

  • 最新版の Firefox や Chrome など、良く WebGL をサポートしているモダンブラウザを使用してください。
  • デモを保存するディレクトリを用意してください。
  • 最新で最小版のThree.js をそのディレクトリに保存してください。
  • ブラウザの別のタブで Three.js documentation を開いてください — 参照するのに便利です。

HTMLの構造

これが今回使用するHTMLのコードです。

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>MDN Games: Three.js demo</title>
	<style>
		body { margin: 0; padding: 0; }
		canvas { width: 100%; height: 100%; }
	</style>
</head>
<body>
<script src="three.min.js"></script>
<script>
	var WIDTH = window.innerWidth;
	var HEIGHT = window.innerHeight;
	/* 私たちの JavaScript コードはここに来ます */
</script>
</body>
</html>

このコード内にはtitleのような基本的な情報とcanvas要素の幅(width)と高さ(height)を定義する CSS があり、Three.js が全体を使えるようにするためにcanvas要素が表示領域全体を埋める必要があります。初めのscript要素でThree.js ライブラリを埋め込み、2つ目のscript要素にサンプルコードを記述していきます。すでに組み込み変数にウィンドウの幅、高さが代入されています。

先に進む前に、このコードを新しいテキストファイルにコピーしデモ用ディレクトリにindex.htmlとして保存しましょう。

レンダラ

レンダラは、ブラウザにおいてシーンを表示する役割を持ちます。デフォルトは WebGL ですが、他にもCanvas や SVG,CSS,DOM といったレンダラがあります。これらは、それぞれシーンがどのようにレンダリングされるかが全く異なり、そのため WebGL と CSS では実装方法が異なります。しかし、レンダリングには様々な方法があるにも関わらず、利用者は全く同じように感じます。この仕組みのおかげで、使いたい技術をブラウザがサポートしていない場合に、サポートされる別のレンダラを使うこともできます。

var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0xDDDDDD, 1);
document.body.appendChild(renderer.domElement);

新しく WebGL レンダラを作成し、前項で指定した画面いっぱいと同じサイズに設定し、DOM に要素を追加します。あなたは初めの行の antialias というパラメータに気づいたかもしれません。これにより、オブジェクトの境界がよりスムーズにレンダリングされます。また、setClearColor()関数を使って背景色をデフォルトの黒から明るい灰色に変更することができます。

このコードを、index.html の 2番目の <script> 要素として、JavaScript コメント直下に追加しましょう。

シーン

シーンは全てが起こる場所です。新たにオブジェクトを作るときは、シーン内にそれを追加することで画面に表示されるようになります。Three.jsではシーンは Scene オブジェクトで表します。前項のコードの下にこれを追加し、シーンを作成しましょう。

var scene = new THREE.Scene();

追加されると、.add()関数を使いオブジェクトをそのシーンに追加できるようになります。

カメラ

私たちは既にレンダリングされたシーンは持っていますが、作業の成果を見るにはカメラが必要になります――カメラのない撮影セットを想像すればいいでしょう――。次のコードでは、カメラを3次元座標の指定位置に配置し、オブジェクトの方に向かせることで、何でも見ることができるようになります。

var camera = new THREE.PerspectiveCamera(70, WIDTH/HEIGHT);
camera.position.z = 50;
scene.add(camera);

前項のコードの下にこのコードを追加しましょう。

カメラは他のタイプ(Cube,Orthographic)も利用できますが、最も簡単なのは Perspective です。これを初期化するには、視野角とアスペクト比を設定する必要があります。前者は見る世界の広さを決め、後者はレンダリングするときにオブジェクトが正しい縦横比で表示されるようにします。上のコードについての解説は以下の通りです。

  • 視野角に70を指定しましたが、様々な値を試すのも良いでしょう。値が高いほど一度に表示される世界が広くなります。魚眼レンズの写真と普通のカメラの写真のような違いです。デフォルトでは50にセットされています。
  • アスペクト比はウィンドウの今の縦横比に合わせ、動的に変化します。勿論比率を固定することもできます。例えば、ワイドスクリーンの16:9などです。デフォルト値は1(1:1)です。
  • 50にセットされたz座標は、カメラとシーンのz軸上の距離を指定します。ここにカメラを置いているので、シーンにあるオブジェクトを眺めることができます。50に指定すれば近すぎたり遠すぎたりせず、オブジェクトのサイズによりますが視野に映ることができるでしょう。xy(もちろんzも)座標を指定しない場合、デフォルトで0がセットされます。

これらのパラメータを調整し、シーンがカメラにどのように映るかを確認する必要があるでしょう。

Note: これらの座標(カメラの z 座標など)のパラメータに決まった単位は存在しないため、シーンに適している単位(ミリメートル、メートル、フィートやマイルでも)で構いません。あなたの決めるところです。

シーンのレンダリング

全ての準備が終わりましたが、まだ私たちは何も目にしていません。レンダラを作ったなら、全てをレンダリングしましょう。render()は、そのレンダリングをrequestAnimationFrame()の助けを借り行います。このコードは、全フレームで常にシーンがレンダリングされるようになります。

function render() {
	requestAnimationFrame(render);
	renderer.render(scene, camera);
}
render();

こうすることで常にフレームからレンダリング処理が呼び出され、レンダラがカメラに映るシーンをレンダリングします。render()を宣言することでこのループが開始され、永遠に続きます。

また、このコードを前項までのコードの下に追加しましょう。ファイルを上書きし、ブラウザで開きます。グレー一色の画面が表示されるでしょう。おめでとうございます!

ジオメトリ

シーンが正しくレンダリングできることが確認できました。次は、3Dシェイプを追加してみましょう。開発を助けるために、Three.jsにはいくつかのプリミティブなシェイプが既に定義されています。このプリミティブを使うと、1行のコードでシェイプを追加することができます。キューブやボール、円柱、さらに複雑な形状もあります。与えられた図形に必要な頂点、面を描画するような処理はThreeが行うため、開発者はより高度なコーディングに意識を向けることができます。

初めに、キューブのシェイプのジオメトリを定義し、前項のrender()の上にこのコードを書きましょう。

var boxGeometry = new THREE.BoxGeometry(10, 10, 10);

このコードでは、10x10x10の簡単な立方体が生成されます。ジオメトリだけでは不十分で、シェイプにはマテリアルが必要です。

マテリアル

マテリアルとは、色やテクスチャとして物体の表面を覆うものです。今回は、前項のキューブに色を付けるためシンプルな青を使います。マテリアルには、Basic,Phong,Lambertといった事前に定義されたものがあります。後で後ろ2つを使ってみましょうか。今はBasicで十分です。

var basicMaterial = new THREE.MeshBasicMaterial({color: 0x0095DD});

前項で追加した定義の下にこれを追加しましょう。

遂にマテリアルも使えるようになりました。さて、次は何をしますか?

メッシュ

マテリアルをシェイプのジオメトリに適用させるには、メッシュを使用します。メッシュは、マテリアルをシェイプの表面に適用してくれます。

var cube = new THREE.Mesh(boxGeometry, basicMaterial);

もう一回前項で追加したコードの下にこれを追加しましょう。

キューブをシーンに追加する

これまでに、ジオメトリやマテリアルを定義してキューブを作り出しました。最後に私たちが行うべきことはシーンに追加することです。さきほどのコードの下にこれを追加してください。

scene.add(cube);

コードを保存してページをリフレッシュすると、オブジェクトがカメラの方向を向いているのでオブジェクトは正方形に見えます。オブジェクトの良いところは、シーン内で移動できるということです。例えば、私たちの思うままに回転や拡大縮小を行ったり。キューブを少し回転させ、複数の面を見てみましょう。また、コードの下にこれを追加します。

cube.rotation.set(0.4, 0.2, 0);

おめでとうございます、あなたは3Dの世界にオブジェクトを生み出しました!これで、あなたが思うよりも簡単であることは証明できたでしょうか? きっとこんな画面があることでしょう。

Blue cube on a gray background rendered with Three.js.

ここまでのサンプルコードは、ここで配布しています。

GitHubでチェックアウトすることもできます。

シェイプやマテリアルの追加

今度は、シーンにシェイプをさらに追加し、色々なシェイプやマテリアル、ライト等々を探検してみましょう。今のキューブを左に動かし、新たな友人のためのスペースを作ってあげます。また、コードにこれを書き足してください。

cube.position.x = -25;

さて、さらにシェイプとマテリアルを追加しましょう。あなたは Phong マテリアルに覆われたリングに何を加えたいですか? キューブを定義するコードの下に、次のコードを書き足してみましょう。 

var torusGeometry = new THREE.TorusGeometry(7, 1, 6, 12);
var phongMaterial = new THREE.MeshPhongMaterial({color: 0xFF9500});
var torus = new THREE.Mesh(torusGeometry, phongMaterial);
scene.add(torus);

これらのコードは、リング状のジオメトリを追加します。TorusGeometry()関数では、半径、管の径、半径の分割数、管の分割数を定義できます。PhongマテリアルはBasicマテリアルより光沢がありますが、今はリングは黒く見えています。

私たちは、事前に定義されたもっと楽しいシェイプを選択できます。もっと遊ぼう。リングを定義するコードの下にこれを書き足しましょう。

var dodecahedronGeometry = new THREE.DodecahedronGeometry(7);
var lambertMaterial = new THREE.MeshLambertMaterial({color: 0xEAEFF2});
var dodecahedron = new THREE.Mesh(dodecahedronGeometry, lambertMaterial);
dodecahedron.position.x = 25;
scene.add(dodecahedron);

このコードで私たちは、12の面を持つ多面体を追加しました。DodecahedronGeometry()関数では、オブジェクトのサイズを定義することができます。このオブジェクトには Lambert マテリアルを使用しています。これは Phong マテリアルと似ていますが、比べると光沢がありません。しかし、やはりこれも黒に見えます。オブジェクトの座標を右にずらしているので、キューブやリングと違う場所に表示されるでしょう。

先程言ったように、新しいオブジェクトは今黒く見えています。Phong、Lambert マテリアルをきれいに表示するには、ライトを導入しましょう。

ライト

Three.jsには様々な種類の光源があります。最も基本的なものは PointLight で、懐中電灯のように光り、決められた方向をスポットライトのように照らします。シェイプの定義の下に、これを書き足しましょう。

var light = new THREE.PointLight(0xFFFFFF);
light.position.set(-10, 15, 50);
scene.add(light);

このコードでは、ライトの照らすべき方向を定義し、その方向をシーンの中心から少しずらすことで全てのオブジェクトの一部を照らすようにし、シーンに追加します。これで3つ全てのオブジェクトがきれいに表示されます。ドキュメントでAmbient,Directional,Hemisphere,spotなど他の光源の種類を調べるのも良いでしょう。是非、シーンに別の種類を配置し、影響を見てみてください。

Shapes: blue cube, dark yellow torus and dark gray dodecahedron on a gray background rendered with Three.js.

しかし、これでは相当退屈です。ゲームの世界は、常に何かが起こっているのです。例えば、アニメーションが表示されたり。だったら、このオブジェクトたちに命を吹き込んで、アニメーションさせてみましょう。

アニメーション

私たちはすでに回転を使ってキューブの位置を調節しました。シェイプのスケーリング、位置の変更を行うこともできます。アニメーションを表示するには、レンダリングのループの中で該当する値を変更します。それがフレームごとに反映されます。

回転

回転の指定は素直です。各フレームで指定された方向に角度を変化させます。このコードを、render()で使ったrequestAnimationFrame()のあとに追加しましょう。

cube.rotation.y += 0.01;

これで、キューブは毎フレームごとに回転してゆきます。少しずつ。そのため、とても滑らかに見えるでしょう。

スケーリング

私たちはオブジェクトをスケーリングすることもできます。値を指定することで、それを成長させたり、縮小させたりできます。もっと面白くしましょう。まず、経過時間をカウントする変数 t を実装しましょう。render()の前に追加してください。

var t = 0;

さて、フレームごとに値が増えるようにしましょう。requestAnimationFrame()のすぐ後にこれを書き足しましょう。

t += 0.01;
torus.scale.y = Math.abs(Math.sin(t));

私たちは Math.sin を使うことで非常に面白い結果を見ることができました。sin()は周期的な値を返すため、リングは大きくなったり小さくなったりを繰り返します。返り値を Math.abs でラップするため、必ず0以上の値を得ることができます。スケールに負の値が指定されたとき、スケーリングは全く予期できません。もしそうであった場合、半分の時間はリングは真っ黒になったでしょう。

遂に、動かします。

動く、動く

回転やスケーリングだけでなく、シーンの中でオブジェクトをさらに自由に動かすこともできます。requestAnimationFrame()のすぐ後にこれを書き足しましょう。

dodecahedron.position.y = -7*Math.sin(t*2);

このコードでは各フレームの y座標に sin() の値を適用することで十二面体を上下に動かします。また、少し調節して、クールに見えるようにしています。この値を変更して、アニメーションにどのような変化が起きるかを見てみるのもよいでしょう。

まとめ

これは最終的なコードです。

あなたは今までのコードをGitHubで見ることもできるし、ローカル環境で遊びたいと思ったらリポジトリをフォークすることもできます。今あなたは Three.js の基本を理解しているでしょう。このページの親ページである Web上の3Dに関するドキュメントに行くこともできます。

WebGLを実際に触ることで、内部で何が起こっているのかをより理解することもできます。私たちのWebGLドキュメンテーションを参考にしてみてください。

ドキュメントのタグと貢献者

このページの貢献者: mdnwebdocs-bot, hamasaki, irimame256
最終更新者: mdnwebdocs-bot,