【WebGL特集】第2回:回転する立方体
※この記事は2013年の記事を2018年5月に加筆修正したものです。three.jsの使用バージョンはr92です。
今回から、webGLの具体的な表示方法を解説していきます。
1、テキストエディタの用意
webGLはテキストで記述していきます。メモ帳でもかまいませんが、記述が多くなるので使いやすいテキストエディタを用意したほうが良いでしょう。webGLはHTMLの中にjavascriptとして記述していきます。webGLと言っていますが、厳密にはjavascriptのライブラリの一つであるThree.jsを使いwebGLを表現しています。今後はややこしくなるのでwebGLという言葉を使っていきます。

2、FireFoxの用意
表示の確認に使用するブラウザは、FireFoxを使います。出来たwebGLのJavaScriptが記述されたhtmlファイルをFireFoxにドラッグ&ドロップして確認するわけです。他のブラウザでも確認できなくはないですが、GoogleChromはセキュリティーの都合によってローカルのwebGLはBlenderで出力したモデリングしたデータなど一部見れないものがあります。

またFireFoxには標準でThree.jsのデバッガがついておりますのでおすすめです。
[Ctrl + Shift + i]でデバッガログを表示。

設定アイコンからCanvasにチェックをいれます。

3、Three.jsのダウンロード
こちらからthree.jsを入手してください。
左メニューにあるdownloadから最新バージョンをダウンロードできます。259Mあります。(2018年5月記事修正時点のバージョンはr92)
重くてダウンロード面倒という方は、Githubからbuildフォルダ以下のthree.jsのみダウンロードしてください。
three.jsはwebGLプログラミングを簡単にするサポートの役割をしてくれます。zipファイルを解凍した先にあるbuildフォルダを覗くと3つのファイルが見つかります。

このthree.jsには2種類あります。ソースの読みやすい「three.js」と、実行速度とファイル容量の軽さを優先した「three.min.js」です。どちらを使っても実行に問題はありませんが、今回はなんとなくthree.jsを使います。three.module.jsについては、今は気にしなくて結構です。
ちなみに、three.jsをわざわざダウンロードしなくてもネット(gdnjs)にアップされているthree.jsのリンク先を記述する方法もあります。ただし追加のモジュールはないのでダウンロードしてしまうほうがよいでしょう。
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></scrip>
4、制作フォルダの用意
デスクトップでもどこでもいいので、フォルダを一つ作っておきます。名前はローマ字表記にしてください。例えば「webGL_Lesson」としておきます。そこに先ほど解凍したbuildフォルダをコピペします。あとはこのwebGL_Lessonフォルダにhtmlファイルを作ってソースを記述していけばよいのです。

5、ソースのコピペで体感
まずは、以下のソースをコピペし、htmlファイルとして、先ほど作ったフォルダに保存します。出来たファイルをFireFoxにドラッグ&ドロップして見てましょう。
<html>
<meta charset="utf-8"/>
<body>
<script src="build/three.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function(){ //windowにイベント追加
//使い回しが多い数値は変数にしておく
var width = 640;
var height = 480;
var aspect = width / height;
//シーン
var scene = new THREE.Scene(); //sceneという変数にはThee.scene()を入れる
//カメラ
var camera = new THREE.PerspectiveCamera( 65, aspect, 1, 1000 ); //左から画角、縦横比、クリッピング近い、クリッピング遠い
camera.position.z = 600;
//オブジェクト
var geometry = new THREE.CubeGeometry(200,200,200);//ジオメトリを用意
var material = new THREE.MeshLambertMaterial( { color: 0x202080 });//ランバートマテリアルを用意
var cube = new THREE.Mesh( geometry, material); //ジオメトリとマテリアルを合体させたものがcubeだ
cube.rotation.set(0.5, 0.5, 0); //cube回転
scene.add( cube ); //シーンに追加
//ライティング
var directionalLight = new THREE.DirectionalLight( 0xffffff, 3 ); //平行光源(色、強度)
directionalLight.position.set(0,0,3);
scene.add( directionalLight );
//レンダラー
var renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
renderer.setClearColor(new THREE.Color('white'));//背景色の設定
document.body.appendChild( renderer.domElement );
//レンダリング
renderer.render( scene, camera );
//キューブを回転させて再描画
function animate(){
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
});
</script>
</body>
</html>
See the Pen webGLBox by 住岡義和 (@mox-motion) on CodePen.
立方体が表示されているはずです。これが、webGLです
6、ソースの解説
three.jsを使って、ブラウザに3Dグラフィックを表示させるためには多くの設定をしなければなりません。
カメラやライトのみならず、シーンやレンダラーの指定までしなければならないのです。
では実際にソースの中身を見ていきましょう。
Three.jsの読み込み
<html>
<meta charset="utf-8"/>
<body>
<script src="build/three.js"></script>
<script>
まず、この文はhtmlですよと宣言します。メタ情報でこのファイルはutf-8を使用していますと伝えます。4行目で、指定したパスにあるthree.jsをロードします。こうすることで、Three.jsが使えるようになります。5行目はここからはhtmlではなく、scriptを書きますよ!と宣言しています。これより先にwebGLの本文を記述します。スマートに書くのであれば、headにスクリプトを記述し、bodyに記載したキャンバスを指定する方法が良いかと思いますが、ここでは行数削減のため割愛。
イベント開始の命令と変数を用意
window.addEventListener("DOMContentLoaded", function(){ //windowにイベント追加
//使い回しが多い数値は変数にしておく
var width = 640;
var height = 480;
var aspect = width / height;
7行目:window.addEventListener~で、以降に記述されたイベントを実行させます。
9~10行目:数値を使いまわす場面がある場合は、こうして変数でまとめて、あとで数値を変更しやすいようにしてあげます。
シーンを用意
//シーン
var scene = new THREE.Scene(); //sceneという変数にはThee.scene()を入れる
シーンという名の空間を用意します。本来webGLのみで表現する場合は複数行の記述になりますが、three.jsを使うと1行で済みます。すごい!
カメラを用意
//カメラ
var camera = new THREE.PerspectiveCamera( 65, aspect, 1, 1000 ); //左から画角、縦横比、クリッピング近い、クリッピング遠い
camera.position.z = 600;
new THREE.PerspectiveCameraでthree.jsのパースペクティブカメラを用意し、カッコ内でパラメーターを指定します。
camera.position.zでカメラのZ位置を指定しています。カメラが原点のままなら原点にあるオブジェクトは見えませんからね。ずらしておきましょう。
キューブオブジェクトを用意
//オブジェクト
var geometry = new THREE.CubeGeometry(200,200,200);//ジオメトリを用意
var material = new THREE.MeshLambertMaterial( { color: 0x202080 });//ランバートマテリアルを用意
var cube = new THREE.Mesh( geometry, material); //ジオメトリとマテリアルを合体させたものがcubeだ
cube.rotation.set(0.5, 0.5, 0); //cube回転
scene.add( cube ); //シーンに追加
立方体オブジェクトをシーンに登場させます。3Dオブジェクトはジオメトリ(形)とマテリアル(皮)で出来ています。まず、その二つをthree.jsで読み込んであげて23行目の new THREE.Mesh()で合体させて立方体を作っています。
初期の回転値を.setでxyz一気に指定します。この回転値はラジアン単位で指定しなければなりません。面倒ですよね。
作ったオブジェクトはそのままでは表示されません。最後にscene.add( cube ); でシーンにオブジェクトを登場させます。
ライトを用意
//ライティング
var directionalLight = new THREE.DirectionalLight( 0xffffff, 3 ); //平行光源(色、強度)
directionalLight.position.set(0,0,3);
scene.add( directionalLight );
ライトがないとオブジェクトが真黒になるので、ライトを用意します。今回はディレクションライトですが、他にもスポットやポイントライトがあります。そこらへんはマニュアルを見たほうが早いでしょう。ライトの位置を指定したら、オブジェクトと同様にscene.add( directionalLight );でシーンに登場させてあげます。
レンダラーを用意
//レンダラー
var renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
renderer.setClearColor(new THREE.Color('white'));//背景色の設定
document.body.appendChild( renderer.domElement );
なんとレンダラーまで用意しなければなりません。レンダラーは主に2種類。3D向けのWebGLRendererと2D向けのCanvasRenderer。今回は3DなのでWebGLRendererを使います。renderer.setSize( width, height );でレンダラーの縦横解像度を指定します。上記のほうで指定した変数をいれていますが、数値を直接指定してもかまいません。renderer.setClearColorで、背景色を指定します。document.body.appendChildは、このhtmlのbody(webページ)でレンダリングせよと命じています。
レンダリングの実行
//レンダリング
renderer.render( scene, camera );
用意したレンダラーを実際にレンダリングさせます。カッコ内でシーンとカメラを指定します。
次で同じことをしているので、なくてもいいのですが、アニメーションが必要ないときのために記述しておきます。
キューブを回転させて再描画
//キューブを回転させて再描画
function animate(){
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate()
アニメーションさせたい場合は、再描画を繰り返す必要があります。基本的に静止画を連続で表示するわけですから。この場合立方体の回転値を更新させつつ再描画をさせることでアニメーションを表現します。
そのためには、回転値の更新と再描画部分を関数でまとめる必要があります。そして最後のanimate()で関数実行を指示します。あとはrequestAnimationFrameが指定した時間後に関数を繰り返し、立方体がアニメーションしているように見せるわけです。
終了の処理
});
</script>
</body>
</html>
ソースの上記のほうで指定したwindow.addEventListener~を }); で閉じます。
次に</script>で、scriptの記述はここまでと宣言し、</body>でbodyを閉じ、</html>でhtmlを終了させます。
以上で第2回は終了です。いかがでしたでしょうか。webGLの取っ掛かりくらいはつかめたのではないかと思います。次回は3Dプレビューらしくカメラをグリグリ回転させる方法を解説していきます。