PlayStation 4でVR(仮想現実)を体験できるPlayStation VRの発売が目前に迫り、いよいよVRが一般家庭へ普及し始めると話題になってます。以前ICS MEDIAでもWebのテクノロジーを使用してVRコンテンツを作成する方法を記事「WebGLではじめるお手軽VR入門」で紹介し、反響をいただきました。

今回は、Webのテクノロジーだけで、かつプログラムも使わずVRコンテンツの作成に挑戦する方法を紹介します。なんと、JavaScriptをかくことなくHTMLにタグを追加するだけでVRコンテンツが作成できるんです!

次のデモは実際に作成したVRコンテンツです。中央の円状のカーソルを牛の3Dモデルに重ねることでアニメーションします。詳しい作成方法は本記事の後半で解説します。

プログラムを使わず作成したVRコンテンツ

※パソコンではドラッグ、スマートフォンではジャイロセンサーが検知した傾きで視点が変わります。右下のアイコンをクリックすると、HMDで閲覧できるモードへ切り替わります。

HTMLをマークアップするようにVRコンテンツを作成しよう

A-Frame公式ページキャプチャー

VRコンテンツをHTMLのマークアップのように作成するには、JavaScriptライブラリ「A-Frameエー・フレーム」を使用します。「やっぱりJavaScriptを使うのか」と思うかもしれませんが、HTMLからこのライブラリを読み込むだけで、VRコンテンツに必要な処理を用意してくれます。

A-FrameのGitHubページで公開されている事例

▲A-Frameを使用して作られたVRコンテンツの事例。A-FrameのGitHubページより引用

A-Frameは、MozillaのVRチームが開発したWebVRフレームワークです。WebVRとは、WebブラウザからOculus RiftなどのHMD(ヘッドマウントディスプレイ)へVRコンテンツを出力する仕組みのことです。このWebVRを採用することで、Webのテクノロジーで作成したVRコンテンツをHMDで体験できるようになります。HMDを持っていない方でも、記事「WebGLではじめるお手軽VR入門」で紹介したGoogle Cardboardとスマートフォンがあれば体験できます。

Google Cardboard

▲Google Cardboard

Google CardboardでVRコンテンツを体験している様子

▲Google CardboardでVRコンテンツを体験している様子

A-Frameを使用したVRコンテンツの作り方をデモを交えて紹介

A-Frameを使用したVRコンテンツの作り方を6つのオリジナルデモで紹介します。本記事では、A-Frameの基本的な使いかたの解説となるため、詳しいことを知りたい方はA-Frameの公式ドキュメントページをご覧ください。

A-Frameを使うための下準備

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

A-FrameのGitHubページからライブラリをダウンロードします。GitHubページの右上にある[Clone or download]ボタンをクリックし、その中から[Download ZIP]をクリックします。すると、ライブラリのデータが入ったZipファイルがダウンロードされるので、任意の場所に展開します。

GitHubページのキャプチャー

2. HTMLからライブラリを読み込む

展開したaframe-masterフォルダー内のdistフォルダーにaframe-v0.3.0.min.jsというJavaScriptファイルがあるので、作業する任意の場所に格納します。そのJavaScriptファイルを、次のようにHTMLから読み込むだけで準備完了です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <!-- A-FrameのJavaScriptファイルを読み込みます -->
  <script src="../assets/js/aframe-v0.3.0.min.js"></script>
</head>
<body>
<!-- A-Frameのタグを記述します -->
</body>
</html>

ボックスを配置するデモ

ボックスを配置するデモ

3D空間(シーン)にボックスを配置するデモです。A-Frameでは、シーンにオブジェクトを追加することでコンテンツを作っていきます。

このデモは3種類の要素をbody要素内に記述するだけで実現できます。まず始めに、3Dを描画するシーンをa-scene要素で追加します。その中にa-box要素(ボックス)とa-sky要素(背景)を追加すると3D空間に表示されます。

<body>
<!-- シーン -->
<a-scene>
  <!-- ボックス -->
  <a-box position="0 0.5 -1.5" rotation="0 45 0" width="1" height="1" depth="1" color="#e67e22"></a-box>

  <!-- 背景 -->
  <a-sky color="#fafafa"></a-sky>
</a-scene>
</body>

a-box要素のposition属性でXYZ軸方向の座標、rotation属性でXYZ軸方向の回転角度、width属性で幅、height属性で高さ、depth属性で奥行き、color属性で色を設定します。

<!-- ボックス -->
<a-box position="0 0.5 -1.5" rotation="0 45 0" width="1" height="1" depth="1" color="#e67e22"></a-box>

a-sky要素でシーンのcolor属性で背景色を設定します。

<!-- 背景 -->
<a-sky color="#fafafa"></a-sky>

ボックスにテクスチャーを設定するデモ

ボックスにテクスチャーを設定するデモ

「ボックスを配置するデモ」で配置したボックスにテクスチャーを設定するデモです。

A-Frame内で外部ファイルを使用するときはa-assets要素内に追加していきます。a-assets要素内に追加した外部ファイルを使用する場合は、オブジェクトのsrc属性で参照します。

<body>
<!-- シーン -->
<a-scene>
  <!-- アセット -->
  <a-assets>
    <img id="texture" src="../assets/images/texture.jpg">
  </a-assets>

  <!-- ボックス -->
  <a-box src="#texture" position="0 0.5 -1.5" rotation="0 45 0" width="1" height="1" depth="1"></a-box>

  <!-- 背景 -->
  <a-sky color="#fafafa"></a-sky>
</a-scene>
</body>

a-scene要素内にimg要素でテクスチャーの画像ファイルを追加します。img要素のid属性でオブジェクトから参照時に使用するID、src属性で画像ファイルのファイルパスを設定します。

<!-- アセット -->
<a-assets>
  <img id="texture" src="../assets/images/texture.jpg">
</a-assets>

a-assets要素内に追加したテクスチャーをボックスに反映します。a-box要素のsrc属性に、テクスチャーIDの先頭に#をつけた文字列を設定します。

<!-- ボックス -->
<a-box src="#texture" position="0 0.5 -1.5" rotation="0 45 0" width="1" height="1" depth="1"></a-box>

3Dモデルを配置するデモ

3Dモデルを配置するデモ

3Dモデルをシーンに配置するデモです。3Dモデルのファイルフォーマットには、多くの3Dモデリング・レンダリングソフトでサポートされているOBJ形式を使用します。

<body>
<!-- シーン -->
<a-scene>
  <!-- アセット -->
  <a-assets>
    <!-- 3Dモデルデータ -->
    <a-asset-item id="cow-obj" src="../assets/obj/spot_quadrangulated.obj"></a-asset-item>
    <!-- マテリアルデータ -->
    <a-asset-item id="cow-mtl" src="../assets/obj/spot_quadrangulated.mtl"></a-asset-item>
  </a-assets>

  <!-- 3Dモデル -->
  <a-entity obj-model="obj: #cow-obj; mtl: #cow-mtl" position="0 1 -1.5" rotation="0 135 0"></a-entity>

  <!-- 背景 -->
  <a-sky color="#fafafa"></a-sky>
</a-scene>
</body>

A-FrameでOBJ形式の3Dモデルを配置するには、3DのモデルデータであるOBJファイルと、マテリアル(オブジェクト上の質感)のデータであるMTLファイルが必要です。a-scene要素内にa-asset-item要素として追加します。

<!-- アセット -->
<a-assets>
  <!-- 3Dモデルデータ -->
  <a-asset-item id="cow-obj" src="../assets/obj/spot_quadrangulated.obj"></a-asset-item>
  <!-- マテリアルデータ -->
  <a-asset-item id="cow-mtl" src="../assets/obj/spot_quadrangulated.mtl"></a-asset-item>
</a-assets>

3Dモデルの描画にはa-entity要素を使用します。obj-model属性にobj: #cow-objで3Dモデルデータを、mtl: #cow-mtlでマテリアルデータを設定します。

<!-- 3Dモデル -->
<a-entity obj-model="obj: #cow-obj; mtl: #cow-mtl" position="0 1 -1.5" rotation="0 135 0"></a-entity>

アニメーションを設定するデモ

アニメーションを設定するデモ

「3Dモデルを配置するデモ」で配置した3Dモデルにアニメーションを設定します。

<body>
<!-- シーン -->
<a-scene>
  <!-- アセット -->
  <a-assets>
    <!-- 3Dモデルデータ -->
    <a-asset-item id="cow-obj" src="../assets/obj/spot_quadrangulated.obj"></a-asset-item>
    <!-- マテリアルデータ -->
    <a-asset-item id="cow-mtl" src="../assets/obj/spot_quadrangulated.mtl"></a-asset-item>
  </a-assets>

  <!-- 3Dモデル -->
  <a-entity obj-model="obj: #cow-obj; mtl: #cow-mtl" position="0 0.5 -1.5" rotation="0 180 0">
    <a-animation
      attribute="rotation"
      dur="5000"
      to="0 540 0"
      repeat="indefinite"></a-animation>
  </a-entity>

  <!-- 背景 -->
  <a-sky color="#fafafa"></a-sky>
</a-scene>
</body>

a-entity要素内にa-animation要素を追加してアニメーションを設定します。attribute属性でアニメーションさせる属性(ここでは角度させたいためrotation)、dur属性でアニメーションの再生時間、to属性でアニメーションの目標値、repeatでアニメーションのリピート回数(ここではループし続けたいためindefinite)を設定します。

<a-animation
  attribute="rotation"
  dur="5000"
  to="0 540 0"
  easing="ease-in-out-back"
  repeat="indefinite"></a-animation>

背景に全天球画像を設定するデモ

背景に全天球画像を設定するデモ

シーンの背景に全天球画像を設定するデモです。背景を単色から全天球画像へ差し替えるだけでグッと没入感が増します。

<body>
<!-- シーン -->
<a-scene>
  <!-- アセット -->
  <a-assets>
    <!-- 3Dモデルデータ -->
    <a-asset-item id="cow-obj" src="../assets/obj/spot_quadrangulated.obj"></a-asset-item>
    <!-- マテリアルデータ -->
    <a-asset-item id="cow-mtl" src="../assets/obj/spot_quadrangulated.mtl"></a-asset-item>
    <!-- 全天球画像 -->
    <img id="sky" src="../assets/images/puydesancy.jpg">
  </a-assets>

  <!-- 3Dモデル -->
  <a-entity obj-model="obj: #cow-obj; mtl: #cow-mtl" position="0 1 -2" rotation="0 180 0">
    <a-animation
      attribute="rotation"
      dur="5000"
      to="0 540 0"
      repeat="indefinite"></a-animation>
  </a-entity>

  <!-- 全天球背景 -->
  <a-sky src="#sky" rotation="0 -130 0"></a-sky>
</a-scene>
</body>

a-assets要素内に全天球画像を追加します。

<!-- アセット -->
<a-assets>
  // 略
  <!-- 全天球画像 -->
  <img id="sky" src="../assets/images/puydesancy.jpg">
</a-assets>

a-sky要素のsrc属性でa-assets要素内に追加した全天球画像を設定します。

<!-- 全天球背景 -->
<a-sky src="#sky" rotation="0 -130 0"></a-sky>

VRコンテンツを操作するUIの実装するデモ

VRコンテンツを操作するUIの実装するデモ

VRコンテンツは視界が奪われてしまうため、キーボードやマウスでの操作は向いてません。そのため、視界の中央にカーソルを配置し、そのカーソルが一定時間とどまったところをアクティブ状態と判断するといったVR独特なUIの実装が必要になります。

<body>
<!-- シーン -->
<a-scene>
  <!-- アセット -->
  <a-assets>
    <!-- 3Dモデルデータ -->
    <a-asset-item id="cow-obj" src="../assets/obj/spot_quadrangulated.obj"></a-asset-item>
    <!-- マテリアルデータ -->
    <a-asset-item id="cow-mtl" src="../assets/obj/spot_quadrangulated.mtl"></a-asset-item>
    <!-- 全天球画像 -->
    <img id="sky" src="../assets/images/puydesancy.jpg">
  </a-assets>

  <!-- カメラ -->
  <a-camera>
    <!-- カーソル -->
    <a-entity cursor="fuse: true; fuseTimeout: 1000">
      <!-- リング -->
      <a-ring
        color="#e74c3c"
        radius-inner="0.01"
        radius-outer="0.015"
        position="0 0 -0.75"></a-ring>
    </a-entity>
  </a-camera>

  <!-- 3Dモデル -->
  <a-entity obj-model="obj: #cow-obj; mtl: #cow-mtl" position="0 0.5 -3" rotation="0 180 0">
    <a-animation
      begin="click"
        attribute="rotation"
        dur="5000"
        to="0 540 0"></a-animation>
  </a-entity>

  <!-- 全天球背景 -->
  <a-sky src="#sky" rotation="0 -130 0"></a-sky>
</a-scene>
</body>

カーソルを常に視界の中央に配置するには、カメラと結びつける必要があります。a-scene要素にa-camera要素を追加し、その中にカーソルとなるa-entity要素を追加します。a-entity要素のcursor属性にfuse: trueでカーソルを有効、fuseTimeout: 1000でアクティブと判断するまでの時間(ここでは1000ミリ秒=1秒)を設定します。

<!-- カメラ -->
<a-camera>
  <!-- カーソル -->
  <a-entity cursor="fuse: true; fuseTimeout: 1000">
    <!-- リング -->
    <a-ring
      color="#e74c3c"
      radius-inner="0.01"
      radius-outer="0.015"
      position="0 0 -0.75"></a-ring>
  </a-entity>
</a-camera>

このデモでは、3Dモデルがアクティブになったらアニメーションが始まるようにするため、a-animation要素のbegin属性にclickを指定します。

<a-animation
  begin="click"
  attribute="rotation"
  dur="5000"
  to="0 540 0"></a-animation>

最後に

今回紹介したデモよりも複雑なVRコンテンツの作成には、JavaScriptでガッチリと実装する必要がありますが、スマートフォンのジャイロセンサーの機能を使って空間をぐるぐる見渡したいコンテンツなどには充分ではないでしょうか。

今まではJavaScriptが得意でない方にはなかなか手が出せなかったWebVRですが、これを期に挑戦してみてはいかがでしょうか。ここぞというときのネタの1つとなれれば幸いです。