ブログ

blog

【WebGL特集】第2回:回転する立方体


※2018/05 加筆修正中

今回から、webGLの具体的な表示方法を解説していきます。

1、テキストエディタの用意

webGLはテキストで記述していきます。メモ帳でもかまいませんが、記述が多くなるので使いやすいテキストエディタを用意したほうが良いでしょう。webGLはHTMLの中にjavascriptとして記述していきます。(実際はThree.jsですが、ややこしくなるので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"></script>

4、制作フォルダの用意

デスクトップでもどこでもいいので、フォルダを一つ作っておきます。名前はローマ字表記にしてください。例えば「webGL_Lesson」としておきます。そこに先ほど解凍したbuildフォルダをコピペします。あとはこのwebGL_Lessonフォルダにhtmlファイルを作ってソースを記述していけばよいのです。

webGL_Lessonフォルダ

5、ソースのコピペで体感

まずは、以下のソースをコピペし、htmlファイルとして、先ほど作ったフォルダに保存します。出来たファイルをFireFoxにドラッグ&ドロップして見てましょう。

		<html>
		<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 rendering(){
				cube.rotation.x += 0.01;
				cube.rotation.y += 0.01;
				renderer.render( scene, camera );
				setTimeout(rendering, 33.333); //setTimeout()は設定時間後に関数を呼び出す命令文です。
				//setTimeout(関数名,時間(単位はミリ秒)) 例えば1000で1秒の秒間1F、秒間30Fにしたいなら 1000ミリ秒/30Fで導き出す
			}
			rendering();

		});
		</script>
		</html>

立方体が表示されているはずです。これが、webGLです

6、ソースの解説

three.jsを使って、ブラウザに3Dグラフィックを表示させるためには多くの設定をしなければなりません。
カメラやライトのみならず、シーンやレンダラーの指定までしなければならないのです。

では実際にソースの中身を見ていきましょう。

<html>
<script src="build/three.js"></script>
<script>

まず、この文はhtmlですよと宣言します。本当はメタ情報とかbodyとか書かなければいけないのですが省略。2行目で、指定したパスにあるthree.jsをロードします。こうすることで、Three.jsが使えるようになります。3行目はここからはhtmlではなく、scriptを書きますよ!と宣言しています。これより先にwebGLの本文を記述します。スマートに書くのであれば、headにスクリプトを記述し、bodyに記載したキャンバスを指定する方法が良いかと思いますが、ここでは行数削減のため割愛。

window.addEventListener("DOMContentLoaded", function(){ //windowにイベント追加
    //使い回しが多い数値は変数にしておく
    var width  = 640;
    var height = 480;
    var aspect = width / height;

5行目:window.addEventListener~で、以降に記述されたイベントを実行させます。
7~9行目:数値を使いまわす場面がある場合は、こうして変数でまとめて、あとで数値を変更しやすいようにしてあげます。

    //シーン
    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で読み込んであげて21行目の 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 rendering(){
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        renderer.render( scene, camera );
        setTimeout(rendering, 33.333); //setTimeout()は設定時間後に関数を呼び出す命令文です。
        //setTimeout(関数名,時間(単位はミリ秒)) 例えば1000で1秒の秒間1F、秒間30Fにしたいなら 1000ミリ秒/30Fで導き出す
    }
    rendering()

アニメーションさせたい場合は、再描画を繰り返す必要があります。基本的に静止画を連続で表示するわけですから。この場合立方体の回転値を更新させつつ再描画をさせることでアニメーションを表現します。
そのためには、回転値の更新と再描画部分を関数でまとめる必要があります。そして最後のrendering()で最初の関数実行を指示します。あとはsetTimeoutが指定した時間後に関数を繰り返し、立方体がアニメーションしているように見えるわけです。

 });
</script>
</html>

ソースの上記のほうで指定したwindow.addEventListener~を }); で閉じます。
次に</script>で、scriptの記述はここまでと宣言し、</html>でhtmlを終了させます。

以上で第2回は終了です。いかがでしたでしょうか。webGLの取っ掛かりくらいはつかめたのではないかと思います。次回は3Dプレビューらしくカメラをグリグリ回転させる方法を解説していきます。

Mox-Motionに興味をお持ちの方はお気軽にご連絡ください!

採用希望の方は・・・