みなさんは「VR:Virtual Reality」という言葉をご存知ですか? 日本語では仮想現実と訳され用語自体は最近生まれたものではないのですが、Oculus Rift(オキュラス リフト)などのVRビューワーの出現で私達にも身近なものになりました。その一方で「3Dソフトって難しそう」「VRビューワーが高価で手が出せない」「そもそも何から手を付けたらいいの?」など、VRコンテンツ制作に対してハードルの高さを感じている方も少なくないでしょう。そんなVRコンテンツをThree.jsGoogle Cardboardを使って安価で手軽に作る方法をご紹介します。

下の動画はOculus RiftでVRコンテンツを体験している様子です。1分10秒のあたりになると体がふらつきはじめ、コンテンツに没入している様子がわかります。

VRの仕組み

動物が物体を立体的に見る方法を立体視といいます。物体と目の間の距離は左右の目で差(視差)があり見えている映像が若干ずれています。その2つの映像を脳内で重ねることで奥行きが生まれ立体的に見ることができるのです。それを平面であるディスプレイで表現するためには、人間が立体的に認識できる微妙な差を計算し、表示しなくてはなりません。そこを手軽に実現させるためにGoogle Cardboardを採用しました。

Google Cardboardを使用している様子

Google Cardboard

Google Cardboardの写真

Google Cardboardは、外装がダンボールでできており、ディスプレイはスマートフォンで代用するため価格も1,000円ほどと格安です(Amazonでも購入できます)。Google Playにて専用アプリが公開されており、中でもポール・マッカートニー氏のライブを体験できるPaul McCartneyは話題になりました。さらに、Web制作者にとって価格以上に嬉しいのが立体視を実現できるThree.jsのライブラリが公開されているということです。今回はそのライブラリを使用してVRコンテンツを作成し、WebGLをサポートしているスマートフォンのWebブラウザで表示させてGoogle Cardboardで閲覧するという構成でご紹介します。

※ライブラリはThree.js用のライブラリですが、ソースコード内を参考にすればその他のさまざまなプラットフォーム(Adobe AIRなど)でもGoogle Cardboardを楽しむことができます。

作成したVRコンテンツのデモ

まずVRのことを意識せずにThree.jsでアニメーションを作成します。それをライブラリに渡すと左右で微妙に視線のずれた表示に変換されます。このずれが両目の視差となり立体視を実現しているのです。さらに、スマートフォンのジャイロセンサーで方向を取得しているので、頭を上下左右へ傾けるとコンテンツ内の視線も傾きます。この視線の同期がさらに没入感を生みます。WebGLをサポートしている環境であれば問題なく動作しますが、描画負荷などの詳しいことは記事「iOS8ブラウザの新機能WebGLは超爆速だった! 各種スマートフォンにおけるHTML5・WebGLの描画パフォーマンス徹底検証」をご覧ください。

※ぜひスマートフォンでご覧ください。画面をタップするとフルスクリーン表示へ切り替わります。PCの場合はマウスドラッグで視線を操作できます。

VRコンテンツを作ってみよう

デモファイルをこちらにアップロードしましたので合わせてご覧ください。

1. ライブラリのダウンロード

Chrome Experiments for Virtual Realityの「DOWNLOAD CODE」ボタンをクリックしてダウンロードします。ダウンロードしたファイルの[www]→[js]→[third-party]→[threejs]内にある下記のライブラリを使用します。こちらのJavaScriptファイルを任意の場所に格納してください(デモでは[js]フォルダー内に格納しました)。

  • DeviceOrientationControls.js
    スマートフォンのジャイロセンサーの傾きをVRコンテンツに反映させるライブラリです。
  • OrbitControls.js
    開発中にPCで確認したいときなどにマウスドラッグで視線を操作できるようにするライブラリです。
  • StereoEffect.js
    立体視を実現させるライブラリです。

2. 表示用HTMLの編集

表示用HTMLのheadタグ内に、先ほどダウンロードしたライブラリとメインの処理を記述するJavaScript(ここではMain.jsとし[js]フォルダーへ格納しました)・Three.jsを読み込むscriptタグを記述します。

<script src="https://cdnjs.cloudflare.com/ajax/libs/Three.js/r71/three.min.js"></script>
<script src="js/StereoEffect.js"></script>
<script src="js/DeviceOrientationControls.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/Main.js"></script>

3. JavaScript

いよいよメインのJavaScriptをMain.jsへ書いていきます(本記事ではThree.jsの詳しい説明は割愛させていただきます)。まずはVRコンテンツをPCで操作できるようにするための処理です。最終的なゴール(スマートフォンでの閲覧)には必要ないため省いてしまっても問題ありません。

// PCで閲覧時にマウスドラッグで操作
controls = new THREE.OrbitControls(camera, element);
controls.rotateUp(Math.PI / 4);
controls.target.set(
	camera.position.x + 0.15,
	camera.position.y,
	camera.position.z
);
controls.noZoom = true;
controls.noPan = true;

つづいてスマートフォンのジャイロセンサーの傾きをVRコンテンツへ反映させる処理です。スマートフォンで閲覧する場合は先程のJavaScriptの処理は不要になるため処理を上書きます。

// スマートフォンの場合はジャイロセンサーでの操作へ変更
window.addEventListener("deviceorientation", setOrientationControls, true);

/**
 * ジャイロセンサーでの操作へ変更します。
 */
function setOrientationControls(e) {
	if (!e.alpha) {
		return;
	}

	controls = new THREE.DeviceOrientationControls(camera, true);
	controls.connect();
	controls.update();

	element.addEventListener("click", fullscreen, false);

	window.removeEventListener("deviceorientation", setOrientationControls, true);
}

/**
 * フルスクリーン表示へ切り替えます。
 */
function fullscreen() {
	if (container.requestFullscreen) {
		container.requestFullscreen();
	} else if (container.msRequestFullscreen) {
		container.msRequestFullscreen();
	} else if (container.mozRequestFullScreen) {
		container.mozRequestFullScreen();
	} else if (container.webkitRequestFullscreen) {
		container.webkitRequestFullscreen();
	}
}

最後に立体視を実現させる処理です。

// レンダラー
renderer = new THREE.WebGLRenderer({antialias: true});

// VR表示へ変換
effect = new THREE.StereoEffect(renderer);

// 繰り返し処理を開始
loop();

/**
 * 繰り返し実行される処理です。
 */
function loop() {
	requestAnimationFrame(loop);
	render();
}

/**
 * レンダリングします。
 */
function render() {
	effect.render(scene, camera);
}

これでVRコンテンツの土台ができました。あとはThree.jsで表現したいアニメーションを作成することで(デモでは立方体が降ってくるアニメーションを作成しました)VRコンテンツの完成です。

開発小ネタ

デモを作成して出てきた小ネタを共有します。

  • スマートフォンはGoogle Cardboardへ正しく固定したほうがいい。
    外装がダンボールなでできているということもあり、固定部分で使われているマジックテープの破損を恐れてふたを閉めず確認を行っていたのですが、視差がうまく重ならずに立体的に見えなくなってしまい「計算がずれているのかな?」とJavaScriptのソースコードとにらめっこするはめになってしまいました。ダメ元でフタを閉めて正しく固定してみると立体的に見えるようになりました。
  • 開発中はBrowserSyncでの自動更新が楽ちん。
    ソースコードを変更する度にスマートフォンを取り出してWebブラウザの更新ボタンをタップしていると開発効率が下がるだけではなく、外装がダンボールでできているGoogle Cardboardの劣化してしまいます。そこをBrowserSyncで自動更新をすることでスマートフォンの出し入れの必要がなくなり開発が楽になりました。

※BrowserSyncでの自動更新については記事「ブラウザ確認が一瞬! Grunt・Gulpと始めるBrowserSync入門」をご覧ください。

最後に

正直なところ、Google Cardboardを触るまでは「ダンボールでできているビューワーってどうなの?」と思っていました。ですが、Oculus Riftなどの高価なビューワーにはかなわないかもしれませんが、1,000円という価格以上にVRコンテンツを楽しむことが出来ました。まずは手の出せる範囲で触ってみて、ある程度VRコンテンツの雰囲気がつかめたら本格的なVRビューワーを購入するという流れでも良いでしょう。2016年にOculus Riftの製品版が一般発売されることもあり、いよいよVRビューワーが一般に普及する時代になってきました。この流れに乗り遅れないためにも積極的に新しい技術・デバイスに触れていくことが大切ではないでしょうか。