A-Frameとは
WebGLレンダラーであるThree.jsベースのMR向けのWebフレームワークです。Three.js単体でもマウスなどからの入力情報を用いつつ3Dモデルをレンダリングすることが出来るのですが、A-Frameを使えばVRデバイスを活用することが出来、またUnityライクなエコシステムを活用することが出来ます。A-Frameは単なるライブラリではなく、UnityのAsset Storeのようなコミュニティを伴っています。
他のライブラリについては以下にまとめてあります。
https://yumenomoto.com/blog/webxr2021-spring/#toc11
まずThree.jsを使ってみる
何が出来るのか、ということですが先にThree.jsの全体感を理解した方がA-Frameで何が出来るのか理解しやすいように思いました。
Wikipediaによると、2010年にRicardo Cabelloさんによって公開されたそうです。
公式のGithubリポジトリを見ると mrdoob のリポジトリに飛ぶのですが、どうやらそれがRicardo氏のアカウントの模様。現在も率先して開発に参加されているようです。
https://github.com/mrdoob/three.js/
プレゼンしている様子の動画がYouTubeにありました。
https://youtu.be/57P8julAaRE
公式サイトは以下です。
https://threejs.org/
大量のサンプルが紹介されています。
https://threejs.org/examples/
何が出来るかはサンプルを斜め読みするよ良いかもしれません。
“code”のところから downloadを選択すると、サンプルコードごとリポジトリデータをダウンロードできます。(!データ量が大きいのでダウンロードの際はお気をつけください!)
https://github.com/mrdoob/three.js/archive/master.zip
サンプルファイルとサンプルに必要なデータも同梱されています。
自分のパソコンでunzipし、サンプルファイルを開くとVRのWebサイトとして視聴することが出来ます。もしVRデバイスをパソコンに繋げば、VRアプリケーションのように視聴することが出来ます。
例えば、以下のサンプルをブラウザで開いてもボールが跳ね回るだけですが、Oculusなどのデバイスで開くと手元のコントローラーが表示されるはずです。
https://threejs.org/examples/?q=vr#webxr_vr_ballshooter
これはつまり、VRゴーグルとコントローラー自体の情報やインプット情報などをブラウザに繋ぎ、ブラウザ上にVR(仮想現実)の状況をレンダリングしてくれているワケです。Three.jsが。
ダウンロードしたリポジトリですが、普通にサンプルのhtmlファイルを開いてもCORSエラーになるかと思いますので、ローカルで簡易サーバーを立てるか、クラウドの安いインスタンスか何かで試すのが良いかと思います。
各種の3Dデータも同梱されているため、そのまま開くだけでサンプル一覧と同じものが表示されます。

インポートする
公式ドキュメントにはunpkgを利用する例の記載があります。
https://www.unpkg.com/three-js/
import * as THREE from 'https://unpkg.com/three@<version>/build/three.module.js';
個人的には、リポジトリをダウンロードしてしまって、そこにあるファイルをインポートした方が良いのではないかなと思います。注意点として、バージョン違いにより動かなくなる(互換性がない?)らしいのと、なにより以下のように jsm (ES6対応モジュール)をインポートしないと使えない機能があるとのことなので…。
Other popular parts of the library — such as controls, loaders, and post-processing effects — must be imported from the examples/jsm subfolder.
https://threejs.org/docs/#manual/en/introduction/Installation
注意点
- サンプルのコードがjsmをインポートをする前提で書かれているので、jsのモジュールを間違えてインポートしないようお気を付けください…。
- もしダウンロードしたリポジトリを利用する場合、相対パスに注意です。
読み込み対応しているファイル種が豊富
VRデバイスの情報をブラウザに繋ぎ、ブラウザ上でレンダリングする…というような機能と、VRにまつわる基本的な機能をサポートしています。
個人的に面白いなと思ったのが、様々なファイルを読み込めるようになっていることです。単に箱や球体などをゴリゴリとレンダリングするだけでなく、既存のファイルを活用したり、3Dモデラ―と分業など出来るのは助かりますね。
以下のようなファイルローダーが用意されています。
- 3DM Loader
- BasisTexture Loader
- DRACO Loader
- GLTF Loader
- KTX2 Loader
- MMD Loader
- MTL Loader
- OBJ Loader
- PCD Loader
- PDB Loader
- PRWM Loader
- SVG Loader
- TGA Loader
カンタンなVR-Webアプリケーションであれば、Three.jsで作ってしまうのもアリだと思いました。
ただ自分でコーディングをしていて以下のような点で悩みました。
Three.jsを使っていて気になったところ
- 冗長的な書き方になってしまったりする
- やりたいことはシンプルなはずなのにコードが長くなる
- そもそもXR利用を前提としていないので物足りないところがある
上述の通り、サッとVR-Webアプリケーションを作るのであればThree.jsで問題無いと思います。ただ、やはりそもそもVRデバイスでの利用を前提としているわけではないので、色々と引っかかる場面がいくつかありました。
様々な形式の3Dデータを読み込むことができ、VRデバイスなどからの情報を受け渡すことが出来、レンダリングも出来るというのでも十分凄いのですが、A-Frameが登場した理由が分かる気がします。
※ QiitaにThree.jsを使っている記事がありました。まさにWebGLレンダラーとして有効活用しているものであり、WebXRで使っていくために誕生したわけではないということが分かるかと思います。
“Three.jsでUIを作る”
https://qiita.com/Yamkaz/items/9862541dd81196f3d149
A-Frameを使ってみる
こちらが公式サイトです。
https://aframe.io/
こちらがGithubです。サンプル集であるShowcaseは、examples/showcaseにあるようです。
https://github.com/aframevr/aframe
A-Frameの特徴
- Three.jsベースであること
A-Frameにはタグがあるのですが、例えば”<a-scene>タグ”はThree.jsにおける sceneオブジェクトと対応しています。Three.jsの各種オブジェクト、メソッドを利用することが出来ます。 - Unity的なところ
例えばPrimitiveについて「これはUnityにおけるPrefabsのようなもの」と公式ドキュメントに記載されています。また、aframe-registryという Unity Asset Storeを参考にしたコンポーネントリストが用意されています。 https://aframe.io/aframe-registry/
Unityのコピーというワケではなく、Unityを参考にしているという感じです。
- VRデバイスサポート
blogを見ると、Oculus Quest2のサポートをしたという見出しが躍っています。サポート状況は以下から確認が出来ます。
https://aframe.io/docs/1.2.0/introduction/vr-headsets-and-webvr-browsers.html#what-are-some-current-headsets
OculusとHTC Viveがサポートされているようです。
コードにおいては以下のようにa-entity Primitiveとoculus-touch-controlsコンポーネントを利用します。
<a-entity oculus-touch-controls="hand: left"></a-entity>
<a-entity oculus-touch-controls="hand: right"></a-entity>
インポートする
htmlのheadに以下のコードを入れます。minifyファイルだけなら、サーバーに置いておいても良いような気もしますが…
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
Primitiveのインパクトが大きい
公式サイトのサンプルコードを貼ってしまうのですが、Three.jsと比較してスリムさに驚きました。
https://aframe.io/docs/1.2.0/introduction
<html>
<head>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
</head>
<body>
<a-scene>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
</a-scene>
</body>
</html>
Three.jsではJavaScriptのコードをガリガリ書いてたようなところが、タグ1行で収まっています…
というか、タグしかありません。
もちろん、それぞれのPrimitiveが何で・何をやっているのかが分からなければ込み入ったことが出来ないのですが、様々なコンポーネントが用意されていることもあり、かなり使えるフレームワークだと思います。
また、Three.jsの強みであるファイル読み込みなども活用できることが強いと思いました。対応しているファイル形式の3Dモデルであれば以下のようにワンラインで終わりです。
<a-entity obj-model="obj: url(/path/to/tree.obj); mtl: url(/path/to/tree.mtl)"></a-entity>
A-FrameからJavaScriptを使う
Componentを使います。
https://aframe.io/docs/1.4.0/core/component.html
A-Frameを実行するHTML(PHPでも)で以下のようなエンティティを書いたとします。
<a-entity id="ctlL" laser-controls="hand:left" raycaster="objects: .collidable; far:2" vr-left-controller></a-entity>
.jsファイルで以下のようにして利用することが出来ます。
AFRAME.registerComponent('vr-left-controller', {
init: function () {
const el = this.el;
el.grip = false;
el.addEventListener('gripdown', function (event) {
//VRコントローラーのグリップを握った時の挙動を書く。ライトを消すとか、音を鳴らすとか
});
el.addEventListener('triggerdown', function (event) {
//VRコントローラーのトリガーを握った時の挙動を書く。ライトを消すとか、音を鳴らすとか
});
},
});
JavaScriptの世界にまで持っていけたら、Three.jsを使うのも問題ないと思うのですがどうでしょうか。A-FrameとThree.jsのバージョンがかなり離れてしまっているので、ご注意ください。
下記のリンク先にあるエンティティを削除するサンプルと、上記のようなトリガーアクションを組み合わせてThree.jsを使ったメッシュやライトを消してみる・足してみる所から始めるのが良いかも知れません。
まとめ
- やりたいことがA-Frameで出来そうであれば、物凄いスムーズに開発が進みそう
- タグ一行では表現し足りない場合はThree.jsをガリガリ使えば良さそう
もしA-FrameでもThree.jsでもやりたいことが出来なそうだと思うのであれば、WebXRではそもそも実現出来ないのかも知れません。あとはUnityやネイティブアプリ開発をすることを考えた方が良いのではないかと思いました。
コーディングをしていて気付かされたこととして、Webアプリケーションと言っても、VRモードと普通の描画モードで異なるUI/UXになるということに注意した方が良いかもしれないと思いました。
ネイティブアプリであればOculusなどのVRデバイスを前提とした利用であることは確定なので気にしなくて良さそうですが、「センサーなど無いパソコンでアクセスされたり、VRデバイスでアクセスされたりする」ということを考えると地味にコードの書き分けが必要になりそうです。
特にVRデバイスにおいてはVR酔いを防ぐために前後に動くのではなく”テレポーテーション的に移動する”ことが推奨されています。ただ、パソコンでアクセスした場合は矢印キーで前後左右に動く形の方がUX的に慣れていると思うので、結局は両方を実装することに…
https://developer.oculus.com/learn/bp-locomotion/
シンクライアント的なアプリであれば、A-FrameとThree.jsでWebXRアプリケーションとして構築することを考えてみるのも良いかもしれません。