OculusのVR Webドキュメント勝手に翻訳してみた

原文 https://developer3.oculus.com/documentation/vrweb/latest/

# Introduction

VR Webガイドへようこそ。

VR Webは、WebのためのVR体験を制作することを助けるためのAPIやその他のテクノロジーのプラットフォームです。VR Webコンテンツには、WebGLとWebVR APIによって作られた没入感のある3DシーンとVRで動作するよう拡張された2Dコンテンツがあります。デスクトップやモバイルのブラウザー上で行える全てのことは、VRでも行えます。

このガイドはVR Web体験の開発を始めるためにWebVR APIとReact VR Javascriptライブラリーを紹介します。また、開発者プレビューのCarmel Webブラウザーも提供します。これを使って作成したVR体験をテストすることができます。

# WebVR

WebVRガイドへようこそ。

ざっくり言うと、WebVRはブラウザーのためのVRヘッドセットのインターフェースAPIです。これは通常二つのフェーズからなります:

* セットアップ。アプリケーションがヘッドセットを検出し、`VRDevice`オブジェクトにより記述され、表示のためのターゲットに設定する。
* フレームごとのレンダリング。セットアップが完了したら、`requestAnimationFrame`ハンドラーはポーズデータを取得し、WebGLで両目の映像をレンダリングし、ヘッドセットに送信します。WebVRを直接扱うためにはJavaScriptとWebGLの知識が必要です。

WebVRは進化中のAPIですが、APIの構成は固まっており、大部分の主要なブラウザーベンダーは2017年中旬にはほぼ利用可能になるだろうと考えています。

開発者プレビューのCarmelはこのAPI構成を対象としています。全てのサンプルとドキュメントはこのバージョンのAPIの使い方を説明します。

## はじめに

開発者プレビューのCarmelは[Oculus Gear VRストアのGallery Appsセクション](https://www.oculus.com/experiences/gear-vr/1290985657630933/)で利用可能です。

Carmelを起動すると、Oculusとサードパーティにより開発されたWebVRベースのサンプルギャラリーが表示されます。サンプルは随時[ギャラリー](https://s3.amazonaws.com/static.oculus.com/carmel/OnlineGallery/index.html)に追加されます。時々チェックしてください。

開発者プレビューのCarmelはいくつかの大事な制限があります。アドレスバーと履歴ベースのユーザーエクスペリエンスが不足していることがわかるでしょう。我々はこのソフトウェアをWebVR開発者のための初期のサンドボックスとして使われるようにだけデザインしました。すでにある2Dウェブコンテンツはまだ表示できません。我々はこれは開発者に可能な限り早くテクノロジーを届けるための最適なトレードオフであると信じています。

### 自分のWebVRコンテンツを起動する

あなたのWebVRプロジェクトをテストするために、`ovrweb` browsable intent スキームを使ってください。詳しくは、[コンテンツを起動する](https://developer3.oculus.com/documentation/vrweb/latest/concepts/carmel-launching-content/#carmel-launching-content)を見てください。

```html
<a href="ovrweb:http://ocul.us/experience">
  HTTPコンテンツへ移動
</a>
<a href="ovrweb:https://ocul.us/experience">
  HTTPSコンテンツへ移動
</a>
```

### デバッグする

CarmelはChromiumをベースに作られているので、Chromeのリモートデバッグ機能を使うことができます。これにより使い慣れたコンソール、タイムライン、プロファイラー、DOMビュワー、アドレスバー、更新などのツールを使用することができます。

もしあなたの端末がまだ開発マシンに接続されたことがない場合は、[コンテンツをデバッグする](https://developer3.oculus.com/documentation/vrweb/latest/concepts/carmel-remote-debugging/#carmel-remote-debugging)を見てください。

代わりに、ほとんどのコンテンツはCarmelを起動する前にデバッグすることができます。Carmelでデバッグを始めるまえに、いくつか知っておくべきことがあります:

* 端末に合うようにカメラをセットアップする方法を知っておく。これは、共通のアイバッファーサイズと視野を計算することを意味します。90度の視野角と片目につき1024x1024のバッファーを使用することをお勧めします。
* You only need to render one eye, but have an adjustment so you can pick which eye to render. This can allow you to swap between the left and right eye and look for bugs. Alternatively render both eyes.
* マウスとデバイスの向きは、頭の向きを模倣するために使用することができるので、ビューを動的に変更することもできます。Expect that first generation frameworks with WebVR support will bake these interaction features in.

### 次にどうする？

さて、WebVR対応デバイスが手元にあり、VR Webの開発を始めるのにもっとも簡単な方法はWebGLの上に、もしくはWebGLフレームワークの上で開発を進めることです。これらのコンテンツはほとんどの端末で動かすことができ、WebVR APIのために拡張することも簡単です。

Oculus Connect 3でReact VRについて発表しました。これはReactの新しいプラットフォームで近いうちに利用可能になります(※2016/12/19時点で、[こちら](https://facebookincubator.github.io/react-vr/)から利用可能)。React VRを使うと、Reactベースのモデルを高機能なUIコンポーネントと共に使用して、次世代のユーザー体験を構築できます。すでに存在するブラウザーにもフォールバックして対応することができます。

さらに、[Carmelスターターキットサンプル](https://s3.amazonaws.com/static.oculus.com/carmel/WebVRSamples/index.html)もチェックしてください。デバイスの検出、表示の要求、ステレオレンダリングの基本について説明します。

Carmelの次の大きなマイルストーンは、VRコンテンツだけでなくすでに存在する2Dコンテンツも表示できるようにすることです。Google、Microsoft、Mozillaのすべてのパートナーとともに、Webの重要なマイルストーンを提供することに熱心に取り組んでいる段階です。スタンダード、セキュリティ、ユーザーエクスペリエンスに焦点を当て、このマイルストーンに向けて取り組んでいます。

詳しくは、その他のドキュメントを見てください。何か質問があれば、問題を報告したい場合は、[フィードバックフォーム](https://goo.gl/forms/vLpxeR99c606RedC3)から連絡してください。


## コンテンツを起動する

Chrome等のAndroid 2Dブラウザーから、`ovrweb`プロトコルのリンクをタップすることでCarmelを起動できます。URLはプロトコルに続けて指定します。下記はどのようにHTMLリンクを作成するかとJavaScriptナビゲーションを`ovrweb`プロトコルを使って実行する例です。

```html
<!-- Carmelを通常のリンクで起動する。http://ocul.us/experience はあなたのURLで置き換えてください。 -->
<a href="ovrweb:http://ocul.us/experience">
  HTTPコンテンツへ移動
</a>
<a href="ovrweb:https://ocul.us/experience">
  HTTPSコンテンツへ移動
</a>

<script>
// JavaScriptからも遷移できます
function onClick() {
  // http://ocul.us/experience はあなたのURLで置き換えてください。
  window.location.href = "ovrweb:http://ocul.us/experience";
}
</script>
```

VRコンテンツの中では、通常のWebナビゲーションの方法でその他のVRコンテンツへ遷移することができます。`ovrweb`プロトコルはCarmelの中でも使用することができますが、必須ではありません。2DのWebサイトへ遷移することは、現在はサポートされていません。


## デバッグする

CarmelはChromiumをベースにしています。なので、Chromeデベロッパーツールを使ってWebVRアプリケーションをデバッグすることができます。USBもしくはWi-Fiで接続できます。

### USBデバッグを有効にする

USBデバッグをするために、以下のように端末を設定します:

1. 設定アプリを開きます。
2. 端末情報を選択します。
3. ビルド番号を7回タップすると開発者向けオプションが現れます。
4. 設定アプリのトップに戻り、開発者向けオプションを選択します。
5. USBデバッグを有効にします。


### Gear VR開発者モードを有効にする

Gear VR開発者モードはGear VRヘッドセットを挿入することなくVRアプリケーションを実行させることによって開発ワークフローを高速化します。

Gear VR開発者モードを有効にするには:

1. あなたの端末のosigファイルで署名したapkをビルドして端末にインストールします。詳しくは https://dashboard.oculus.com/tools/osig-generator/ を見てください。
2. 設定アプリを開きます。
3. アプリケーション > アプリケーション管理 を選択します。
4. Gear VR Serviceを選択します。
5. ストレージ > ストレージを管理 を選択します。
6. VR Service Versionを開発者モードが表示されるまで数回タップします。
7. 開発者モードを有効にします。


### Wi-Fiデバッグを有効にする

Gear VRヘッドセットに接続している間にデバッグしたい場合、Wi-Fiデバッグを使用してください。Gear VRに接続している間はUSBデバッグができないため、Wi-Fiは必須です。

Wi-Fiデバッグを有効にするためには:

1. **USBデバッグを有効にする**の手順を完了してUSBケーブルでマシンに接続してください。
2. Android Studioをインストールしてください。
3. terminal または Windows コマンドプロンプトを開いてください。
4. PATHが通っていない場合はadbツールのある場所へ移動してください。Windowsでは、通常`C:\Users\user\AppData\Local\Android\sdk\platform-tools`です。
5. ターミナルウィンドウで、`adb tcpip 5555`と入力してください。
6. 設定アプリを開いてください。
7. 端末情報 > ステータス と移動し、IPアドレスを取得してください。
8. ターミナルウィンドウで、`adb connect x.x.x.x:5555`と入力してください。*x.x.x.x*はIPアドレスです。


### Chromeデベロッパーツールでリモートデバッグセッションを開始する

Carmelにアプリケーションを読み込んだあと、Chromeデベロッパーツールを使ってリモートデバッグできます。

リモートデバッグセッションを開始するためには:

1. Carmelにアプリケーションを読み込んでください。
2. Chromeを起動してChromeデベロッパーツールを開いてください。
3. **More tools > Remote devices**を選択し、Remote devicesタブを開いてください。<br>![webvr-chrome-remotedevices.png](https://qiita-image-store.s3.amazonaws.com/0/56668/03255944-1d44-558f-f84f-63d3404f80a2.png)
4. リストからデバイスを選択してください。
5. **com.oculus.carmel.player_apk**の次の**Inspect**ボタンをクリックしてください。

Chromeデベロッパーツールのリモートデバッグについて詳しくは https://developers.google.com/web/tools/chrome-devtools/remote-debugging/ を見てください。


## WebVR APIの紹介

CarmelはW3C WebVR仕様をサポートしており、WebGLを使ってVRコンテンツを表示することができます。あなたのアプリケーションをVR表示モードに対応させるためのいくつかの簡単なステップがあります。

### 最初のセットアップ

まず、WebGLキャンバスと全てのWebGLシーンレンダリング状態をセットアップします。WebGLキャンバスはVRLayerソースとして表示するために使われます。

```js
var layerSource;

function initWebGLProgram() {
  layerSource = document.getElementById("webgl-canvas");

  // シェーダーをコンパイルする...
  // テクスチャーを読み込む...
  // ジオメトリーを作成する...
  // attributes と uniform ロケーションを保存する
}
```

次に、`window.navigator.getVRDisplays`を使って利用可能なVRDisplaysを取得します。`getVRDisplays`メソッドが`window.navigator`に存在することを検証し、WebVRをサポートしないブラウザーのためにフォールバック処理を実装するべきです。

```js
if (navigator.getVRDisplays) {
  navigator.getVRDisplays().then(function (displays) {
    if (displays.length > 0) {
      // We reuse this every frame to avoid generating garbage
      frameData = new VRFrameData();

      vrDisplay = displays[0];

      // We must adjust the canvas (our VRLayer source) to match the VRDisplay
      var leftEye = vrDisplay.getEyeParameters("left");
      var rightEye = vrDisplay.getEyeParameters("right");

      // canvas の width と height をアイパラメーターを基準に変更する。
      // 単純化のために、両目を同じ解像度で表示する。
      layerSource.width = Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2;
      layerSource.height = Math.max(leftEye.renderHeight, rightEye.renderHeight);

      vrDisplay.requestPresent([{ source: layerSource }]).then(function () {
        vrDisplay.requestAnimationFrame(onAnimationFrame);
      }).catch(function (err) {
        // requestPresentに失敗した
      });
    } else {
      // VRディスプレイが接続されていない。
    }
  }).catch(function (err) {
    // このコンテキストではVRディスプレイにアクセスできない。
    // おそらく`allowvr`属性の付いていない`iframe`の中で実行している。
  });
} else {
  // このブラウザーではWebVRはサポートされていない。
}
```

`navigator.getVRDisplays`を呼ぶことでPromiseが返却されます。これは利用可能なVRDisplaysでresolveされるか、VRDisplaysへのアクセスが禁止されている場合はrejectされます。ここから取得されるVRDisplaysは、VRデバイスが接続されていない場合は空になります。Carmelでは常に一つのVRDeviceが利用可能です。

VRDisplayはWebGLキャンバスの大きさを知るために両目のパラメーターを取得できます。レンダーループでデバイスの向きを取得するために再利用可能な`VRFrameData`を作成することもできます。

VR表示を開始するためには、`VRDisplay.requestPresent`を呼ばなければいけません。通常これはユーザー入力の結果としてしか呼び出せません(タップや“Enter VR”ボタンのクリック等)。しかしCarmelは`VRDisplay.requestPresent`をユーザー入力なしに呼び出せます。

最後に、アニメーションフレームをリクエストするために`VRDisplay.requestAnimationFrame`を使います。


### レンダーループ

VR表示の準備ができてアニメーションフレームを受信するようになったら、VRDisplayのフレームデータを受け取ってシーンをレンダリングし、アニメーションフレームを要求し続ける必要があります。

`VRDisplay.getFrameData`を呼ぶことでVRDisplayの向きに基づいた左目と右目のビュー行列とプロジェクション行列を取得します。これらの行列はそれぞれの目にシーンをレンダリングするために使います。

```js
function onAnimationFrame(timestamp) {
  // Continue to request frames to keep the render loop going
  vrDisplay.requestAnimationFrame(onAnimationFrame);
    
  // Clear the layer source - we do this outside of render to avoid clearing twice
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Update the scene once per frame
  update(timestamp);

  // Get the current pose data
  vrDisplay.getFrameData(frameData);

  // Render the left eye
  gl.viewport(0, 0, layerSource.width * 0.5, layerSource.height);
  render(frameData.leftProjectionMatrix, frameData.leftViewMatrix);

  // Render the right eye
  gl.viewport(layerSource.width * 0.5, 0, layerSource.width * 0.5, layerSource.height);
  render(frameData.rightProjectionMatrix, frameData.rightViewMatrix);

  // Submit the newly rendered layer to be presented by the VRDisplay
  vrDisplay.submitFrame();
}

function update(timestamp) {
  // Update your scene state
}

// For VR, it's important that your render method is parameterized by the camera
// (projection and view matrices) so that it can be used to render from each
// eye's perspective
function render(projectionMat, viewMat) {
  // Render your scene using the given matrices
}
```

両目のレンダリングが完了したら、`VRDisplay.submitFrame`を呼んで新しいフレームを送信します。新しいフレームが利用可能になったら、アニメーションコールバックは再度実行されます。

完全なサンプルは[こちら](https://s3.amazonaws.com/static.oculus.com/carmel/WebVRSamples/HelloWebVR/index.html)。