Three.jsを用いた3Dコンピュータ・グラフィックス


WebGLは、OpenGLというパソコン用の3D API(グラフィックスカードの能力を引き出し、三次元の絵を作り出すためのAPI)を、Webブラウザに移植したものでした。WebGLはこのOpenGL ESをベースに、Webブラウザ向けに微調整されて出来た規格なのです。いわば、OpenGL ES for Webとでも言えます。

 Three.jsは、WebGLのためのJavaScriptライブラリなので、HTML5で3Dコンテンツを制作するためのJavaScriptライブラリになっています。Mr.doob氏が中心となって開発されており、オープンソースソフトウェアとして個人・商用でも無償で利用できます。前のページで見た通り、Three.jsのライブラリを利用すると、プログラムの記述が極端に少なくて済みます。

 このページでは、JavaSCriot ライブラリであるThree.js を用いたWebGL の初級程度の利用法を紹介します。ここでは、OpenGLでのシェーディング言語、および、WebGL そのものの説明は行いません。WebGLについては、WebGLのページを読んでください。JavaScript の初歩的な知識があるといいかも知れません。
以下の例はThree.js公式ページの3DCGの例です。

この例を再生する

関連記事
Blenderのページ
WebGLのページ
OpenGLのページ
Swiftのページ
Metalのページ
GitHub repositories

Last updated: 2019.3.16



****************************************************
Three.js ライブラリを用いた3D CG の基本
****************************************************


まず最初に作成すべきファイルは、スケルトンのhtml ページです。

Three.jsの公式ページの説明では、Three.jsを書き始める時のhtmlのスケルトン・ページは以下のようになっています。


 Three.js の解説書として有名な『初めてのThree.js」(Jos Dirksen著)では、スケルトン・ページの書き方は以下のように設定されています。

どちらを採用すべきは各自の好みに委ねます。

 ライブラリ"three.js"はCDN(コンテンツ・デリバリー・ネットワーク)で提供されているURLからダウンロードして使うこともできるので、

の部分は、

と変えてもいいと思います。

 なお、ICS MEDIAさんのチュートリアル・サイトの説明では、スケルトンhtml は以下のような仕様になっています。

参考までに取り上げました。

 空間にグラフィックスを描画するためには、物体、それを写すカメラ、そして、物体が見えるための光源が必要です。 これらの3要素を配置する空間を[scene(シーン)]と言います。プログラムでは、最初にこのシーンを作成しなければいけない。以下のように記述します。

var scene = new THREE.Scene();


JavaScript での典型的なインスタンスの作成方法です。シーンでは、現実世界での人間の目がカメラになります。ですから、カメラがないと何も見えません。カメラの位置とその方向がシーン中で何が映るかを決めます。カメラをセットアップするために、vertical field of view (fov), an aspect ratio, a near plane, and a far planeを定める必要があります。fov とはカメラの角度のことです。aspect ratio は画面(ウインドウ)の横幅と縦幅の比率のことです。 near plane とは、カメラが写す最も近影までの距離、far plane はカメラが映し出す最終距離のことです。JavaScriptでは以下のように記述します。

// add a camera
// THREE.PerspectiveCamera(fov, aspect, near, far)
var camera = new THREE.PerspectiveCamera(
  75, 
  window.innerWidth/window.innerHeight, 
  0.1, 
  1000
);

// place the camera at z of 100
camera.position.z = 100;

 canvasにレンダリングして映像を書き入れる命令について説明します。rendering とはGPUが影をつけてディスプレイに映し出すことです。以下のように、// add a renderer の後の命令文のように記述します。renderer というインスタンスを作成して、appendChild関数でHTMLのbody要素(この例2では、div要素)にカメラの映像の中身を入れます。
// add a renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
// add the renderer element to the DOM so it is in our page:example1
document.body.appendChild( renderer.domElement );
        // add the output of the renderer to the html element:example2
        document.getElementById("myWebGL").appendChild(renderer.domElement);


 [scene]に、カメラと物体が存在しても、光がなければ何も映りません。光源を設定する必要が出てきます。three.js では、様々な色の光源と照射方向や反射効果などを設定できる命令文があります。


/* we need to add a light so we can see our cube - its almost
as if we're turning on a lightbulb within the room */
var light = new THREE.PointLight(0xFFFF00);
/* position the light so it shines on the cube (x, y, z) */
light.position.set(10, 0, 25);
scene.add(light);


 ”scene.add(light);”で[scene]に光源を追加しています。最後に、[scene]に物体を配置しましょう。立方体を配置するときは、以下のように記述します。

/* we're creating a cube to put in our scene - don't worry
if you don't follow this part, we'll cover geometry and materials
in future posts */
var geometry = new THREE.BoxGeometry(20, 20, 20);
var material = new THREE.MeshLambertMaterial({color: 0xfd59d7});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);


 ”scene.add(cube);”で[scene]に物体(立方体)を追加しています。

 これらを完成させると、以下のプログラムになります。以下をクリックするとこのプログラムが実行されます。

 Three.min.jsはJavaScriptのライブラリですが、このファイルを読み込むことによってはじめてThree.jsが利用できるようになります。CDN(コンテンツ・デリバリー・ネットワーク)で提供されているURLを使います。"var render = function () "でrender関数を定義して、render()でGPUに命令を送っています。

 HTMLでグラフィック関連のタグとして追加された canvas は、その名の通り図形や画像を描画するためのキャンバスとして動作するタグで、javascript を使って操作します。もちろん、Three.js もこの canvas を利用することになるので、コード を記述する前に canvas タグについて簡単に解説します。canvas要素には属性としてid(ID値)を設定することもできます。この場合、以下のように記述します。

canvas要素の内容はJavaScriptを使って設定します。

****************************************************
Three.js ライブラリGeometryの使用法
****************************************************


 すでに、箱を描くプログラムを実行しました。球体の3D CGを作成するときは、'sphereGeometry'を使用します。箱を作成という部分を以下のように修正します。

 // 球体を作成
  const geometry = new THREE.SphereGeometry(300, 30, 30);
  const material = new THREE.MeshStandardMaterial({color: 0xFF0000});
  // メッシュを作成
  const mesh = new THREE.Mesh(geometry, material);
  // 3D空間にメッシュを追加
  scene.add(mesh);

 JavaScriptコード全体は以下のようになります。

以下のファイルを開いてください。球体の3Dグラフィックスが描かれます。ICS MEDIAさんのチュートリアル・サイトから引用しています。

 球体上のような形状がThree.jsで扱える基本的な形状として、いくつか用意されています。代表的なものは、
平面
球体
直方体
三角錐
円柱
カプセル形状
ドーナツ形状
などです。Three.jsでは形状とマテリアルを結合しメッシュを作成することによって、表示可能な3Dのオブジェクトを得ることができます。具体的なコードは、ジオメトリをドーナッツ状のケースのとき以下のように記述します。

var geometry = new THREE.TorusGeometry( 10, 3, 16, 100 );
var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var torus = new THREE.Mesh( geometry, material );
scene.add( torus );


 Torus に変更すると、以下のようなファイルになります。ここをクリックしてグラフィックスを表示してください。

 ジオメトリを自由に変形して自由な立体図形を描くことができます。例えば、直方体の頂点数を増やしたり、頂点座標をランダムに変化させるとどのような立体図形が生まれるのでしょうか。JavaScript を以下のようにします。


ここをクリックしてグラフィックスを表示してください。

どんな立体図形が描かれているでしょうか?


****************************************************
Three.js ライブラリMaterialの使用法
****************************************************


 描画物体のマテリアルに画像を使用する方法について説明します。マテリアルとは描画物体の質感設定のことです。見栄えを決める「マテリアル」を指定して、たとえば、着色や画像・陰影の割り当て、ライティングの反射などを適用できます。マテリアルに画像を使うには読み込み処理を作る必要があります。'THREE.TextureLoader'クラスを使って次のように指定します。地球儀のような球体が描画されます。

// 画像を読み込む
var loader = new THREE.TextureLoader();
var texture = loader.load('image/earthmap.jpg');
// マテリアルにテクスチャーを設定
var material = new THREE.MeshStandardMaterial({
  map: texture
});


この部分を追加した以下のファイルを開いてください。
 次に、マテリアルにMeshStandardMaterial ではなくて、MeshPhongMaterial を使用した例を取り上げます。THREE.MeshPhongMaterialクラスはフォン・シェーディングと言う、光沢感のある質感を表現できるマテリアルです。 以下のように、マテリアルの部分を修正します。図形は8面体です。

// add icosahedron
var geometry = new THREE.OctahedronGeometry( 20 );
var color = new THREE.Color( "#7833aa" );
var material = new THREE.MeshPhongMaterial( {color: color.getHex()} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );


以下のファイルを開いてください。8面体が回転するグラフィックが表示されます。『初めてのThree.js』(Jos Dirksen著)から引用。



****************************************************
Three.js でのAnimationの設定
****************************************************


 以上までに、
mesh のposition & rotation
geometry & material
camera のposition & rotation
lighting のposition & direction
などの要素の使用法についてある程度まで学習しました。 ここでは、簡単なアニメーションの使用法について取り上げます。

アニメーションを描画するためには、requestAnimationFrame関数を用います。最初に、シーンを初期化するためにrender()関数を呼び出して、render()関数内でrequestAnimationFrameを使用します。以下のコードのように記述します。
// call the render function
var step = 0;
var scalingStep = 0;

var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
this.scalingSpeed = 0.03;
};


...

render();

function render() {
stats.update();
// rotate the cube around its axes
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;

// bounce the sphere up and down
step += controls.bouncingSpeed;
sphere.position.x = 20 + (10 * (Math.cos(step)));
sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));

// scale the cylinder

scalingStep += controls.scalingSpeed;
var scaleX = Math.abs(Math.sin(scalingStep / 4));
var scaleY = Math.abs(Math.cos(scalingStep / 5));
var scaleZ = Math.abs(Math.sin(scalingStep / 7));
cylinder.scale.set(scaleX, scaleY, scaleZ);

// render using requestAnimationFrame
renderer.render(scene, camera);
requestAnimationFrame(render);

}
...


この例では、シーンの中に、3種類のジオメトリ、cube, sphere, cylinder が描かれています。 以下は『初めてのThree.js』(Jos Dirksen著)で提供されているコードを用いた簡単なアニメーションの例です。

この例を再生する


そう少し複雑な例を見てみましょう。以下の布が風になびくanimation の例はhttps://threejs.org/examples/の一つです。

再生する

 Blenderで描いたアニメーションCGをGLBファイル形式でexportして、このファイルをGLTFLoader.jsで読み込んでThree.jsで再現できます。以下のロボット兵士のアニメーションがこの例です。

再生する

 SEA3D Studioで作成されたファイルからThree.js用のファイルにexportされた3Dアニメーションの例を以下に挙げます。

再生する

***********************************************************
音声付き3DCGアニメーションをWebGLで再現する
***********************************************************


 最初に。音声データを3D表現する例を取り上げてみます。Three.js公式ホームページにあるWebAudioのSound Visualizerの例を修正してみました。
webAudio_visualizerのexampleを再生

 Blender Studioが制作したショートムービー'Sintel - Third Open Movie by Blender Foundation'のビデオ音声を用いて、映像をThree.jsで描画したexampleがThree.js公式ホームページにあります。下の写真はSintelの一場面を描いたものです。全体の映像はYouTubeで見れます。

Three.jsのexampleを再生する

 日本でよく知られているCGアニメーションの代表例は初音ミクが歌ってダンスをするMikuMikuDance(ミクミクダンス)です。MikuMikuDanceは、樋口優氏が制作した、プリセットされたキャラクターの3Dモデルを操作してコンピュータアニメーションを作成する3DCGソフトウェアです。略称でMMDと呼ばれます。デフォルトで初音ミクなどVOCALOIDキャラクターの3Dモデルを使用できるほか、オリジナルのキャラクターモデルやアクセサリを組み込んで操作することも可能です。Three.jsにMMDを読み込むソフトMMDLoaderが開発されているので、WebGLで再現することができます。 MMDLoaderを用いたMikuMikuDanceの例:

MikuMikuDanceを再生(Safariでは音声が出ません)
webgl_mmdloaderのexample(Safariでは音声が出ません)

 VOCALOIDモデル付属の 3DCG動画制作ツール「MikuMikuDance」ソフトの始め方・使用法の紹介はVPVPwikiを参照してください。MMDの使用に関して、以下のように説明されています。「ドラマチックに用意されたシナリオや、明確なゴールがあるゲームではありません。 MMDには人それぞれの楽しみ方があり、またそれは誰かによって定められるものでもありません。MMDはWindows XP/Vista/7/8/10 上で動作するフリーウェアです。 誰でもダウンロードして楽しむことができます。 オリジナルのユーザモデルやアクセサリ、モーションなどを様々な作者が公開しています。 それらをダウンロードして自分のPC上で組み合わせて楽しむことができます。」ここに明記されている通り、もともとのMMDソフトのプラットホームはWindowsですが、上で行ったように、青柳氏が開発したMMDLoaderを利用して、WebGLで描画すれば、OSの種類に依存しなくなります。

 青柳氏が開発して提供するMikuMikuDanceのMMDLoader sample appsはこのGitHubサイトにあります。この中のMikuMikuDanceを再生(Safariでは音声が出ません)音声を出すためには、自分のPCでAppsを展開して、再生してください。上の例では、Web Audio APIを用いて音声を処理しますので、再生してもこれらに対応していないブラウザでは音声が出ません。FireFoxやChromeでは音声が出ますが、Safariやスマホなどでは音声が出ません。


****************************************************
カメラの移動とコントロール
****************************************************


Three.jsには多数のカメラカメラコントロールがあり、シーン内のカメラを自由に移動させることができます。これらのコントロールのうち、以下のコントロールがよく使用されます。
TrackBallControls: 最も多用されるコントロールで、マウスを使用してシーン内を自由に移動させる
FlyControls: フライトシミュレーションのような移動をコントロールする
FirstPersonControls: 一人称視点のシューティングゲームのような動作をさせる
OrbitControls: 特定のシーンを回る軌道上の衛星のようにカメラを移動させる

 TrackBallControlsを使用するときは、以下のようにJavaScriptファイルを読み込む必要があります。

 このコントロールを用いてカメラの位置を更新するためには、rende()関数内で

のように書きます。

 カメラは以下のような操作でコントロールできます。
マウス左ボタンを押しながらドラッグ:カメラの回転と傾斜
マウスホイールの回転:ズームイン、ズームアウト
マウス右ボタンを押しながらドラッグ:シーンをパン(パンとはカメラを固定してレンズの視野を横方向に動かすカメラワークを言います)

 TrackBallControlsのカメラ操作はこの例で練習してください。
 FlyControlsを使用するときは、以下のようにJavaScriptを読み込むコードを書きます。

 このコントロールを用いてカメラの位置を更新するためには、render()関数内で

のように書きます。

 カメラは以下のような操作でコントロールできます。
マウス左ボタンのクリック:カメラが前に移動
マウス右ボタンのクリック:カメラが後に移動
マウスの移動:カメラの移動

 FlyControlsのカメラ操作はこの例で練習してください。なお、このFlyControlsとFirstPersonContolsのカメラ例は、『初めてのThree.js」(Jos Dirksen著)で提供されているものです。


 FirstPersonControlsを使用するときは、以下のようにJavaScriptを読み込むコードを書きます。

render()関数は上の例と同じように記述します。キーボードの上下左右カーソルキーでカメラを移動させます。周囲を見るときは、マウスを移動させます。

 FirstPersonControlsのカメラ操作はこの例で練習してください。

 カメラのOrbitControlsの詳細は、公式ページを参照ください。

**************


続く 
Three.js でコンピュータ・グラフィクスを楽しんで描こう
**************

Blenderのページに行く
トップ・ページに行く