Oculus GoでWebVR APIを試してみる
UI開発者 加藤今月の初めにスタンドアロン型のVRヘッドセット「Oculus Go」が発売されました。これまでのヘッドセットは高スペックのPCが必要なタイプや、スマホを装着するタイプが一般的でしたが、スタンドアロン型はヘッドセットさえあれば手軽にVRを体験することができます。これまでのものより価格も安くなっており、より一般消費者向けのデバイスと言ってもいいかもしれません。
さて、Oculus Goにはブラウザが標準搭載されておりPCと同じように使用することができます。操作はマウスの代わりに付属のコントローラーを使用します。
先端についているトリガーでクリックが、タッチパッド部をスワイプすることでスクロールができます。ただし、JavaScriptからコントローラーの操作を処理する場合、トリガーはtouchstart
やtouchmove
などのタッチデバイスと同じイベントを使う必要があります。お絵かきアプリなどを作るときは注意しておきたい点です。
下記は実際の画面です。
ご覧のとおり画面が湾曲していますが、その他はPCで見た場合とほぼ遜色ありません。Oculus Goにはシェア機能がついており、本体とFacebookアカウントとの連携が済んでいればすぐにライブ配信を開始することができます。実際に録画をした動画は若干揺れがあり、録画する際は手ぶれ補正ならぬ「頭ぶれ補正」が必要だと感じました。
Oculus GoのブラウザはAndroid 7.0搭載のChrome相当の機能を持ち、WebVR APIを実行することができます。WebVR APIはブラウザからヘッドセットの情報を取得したり、VRモードの開始、終了を制御したりするためのAPIです。
※WebVR APIはWebXR Device APIに置き換えられており、仕様が変わる可能性がありますがOculus GoのブラウザではWebXR Device APIがまだサポートされていないため、今回はWebVR APIのご紹介となります。
ブラウザ上の表示から、ヘッドセット全体の表示に切り替える処理は下記のようになります。
const canvasElement = document.getElementById('myCanvas');
// getVRDisplaysを使用して、ブラウザからアクセスできるヘッドセットを探索します。
navigator.getVRDisplays().then(function(displays) {
if(displays.length > 0) {
// ブラウザ上での表示からヘッドセット全体での表示に切り替えます。
vrDisplay = displays[0];
vrDisplay.requestPresent([{source: canvasElement}]).then(function() {
// 表示の切り替えに成功したら、canvasへの描画を開始します。
});
}
});
実際は表示を切り替えるためのボタンを用意し、ユーザーの操作で表示を切り替える必要があります。また付属コントローラーの戻るボタンを押すとVRモードが解除できるのですが、ただ解除するだけだとcanvasがVR用にレンダリングされた状態のままになってしまうため、vrdisplaypresentchange
イベントを使用してモードの変更を検知し、適宜正しいレンダリングを行うなどスクリプト側で制御が必要です。
VRコンテンツにおいて特に重要なヘッドトラッキングは、WebVR APIに含まれる「VRFrameData」インターフェースを利用することで実現できます。VRFrameDataは射影行列とビュー変換行列の値を持っています。canvasを左目用と右目用の2画面に分割し、2つの行列をカメラとシーンに適用するだけです。three.jsの利用が前提ですが、レンダリング処理は下記のようになります。
function render() {
const WIDTH = width * 0.5;
const HEIGHT = height;
vrDisplay.getFrameData(frameData);
renderer.clear();
// 左目用の画像を描画
renderer.setViewport(0, 0, WIDTH, HEIGHT);
camera.projectionMatrix.fromArray(frameData.leftProjectionMatrix);
scene.matrix.fromArray(frameData.leftViewMatrix);
scene.updateMatrixWorld(true);
renderer.render(scene, camera);
renderer.clearDepth();
// 右目用の画像を描画
renderer.setViewport(WIDTH, 0, WIDTH, HEIGHT);
camera.projectionMatrix.fromArray(frameData.rightProjectionMatrix);
scene.matrix.fromArray(frameData.rightViewMatrix);
scene.updateMatrixWorld(true);
renderer.render(scene, camera);
// レンダリングしたフレームをヘッドセットに送信します。
vrDisplay.submitFrame();
vrDisplay.requestAnimationFrame(render);
}
もちろんVR用のボタンを追加したりなど他にも調整は必要ですが、Web標準技術だけでVRコンテンツを作ることができます。Oculus Goの登場で手軽にVRを体験できるようになり、WebVR APIを使えば手軽にVRコンテンツを作ることができます。この手軽さは今後ますますVR業界を発展させる重要なポイントとなりそうです。
一方でVR上のユーザーインターフェースはまだ決まりきっていないような気がしています。Oculus Goにはポジショントラッキング機能がついていないため、回り込んで見るといったことができませんが、寝そべりながらブラウジングをしたり、動画を見たりなどユーザーによって様々な使い方があります。どんなインターフェースが使いやすいのか研究していきたいと思います。