Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
非推奨;: この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。
メモ: WebVR API は WebXR API に置き換えられました。 WebVR は標準として批准されることはなく、ごく少数のブラウザーでしか既定で実装・有効化されず、少数の端末しか対応していませんでした。
WebVR API はウェブ開発者のツールキットへのすばらしい追加機能で、 Oculus Rift のようなバーチャルリアリティハードウェアへのアクセスが可能となります。そして出力された動きや向きはウェブアプリの描画更新に変換されます。しかし VR アプリを開発はどのようにやればいいのでしょうか? この記事では、それに関する基礎的な解説を行います。
始めるには、次のものが必要です。
対応している VR ハードウェア
使用した場合、 VR 専用ハードウェアを使用して VR シーンのレンダリング/表示を処理するのに十分な性能のコンピューター。購入する VR の関連ガイド(例: VIVE READY コンピューター)を見ていただくと、必要なものがわかると思います。
対応しているブラウザーがインストールされていること - 最新のFirefox Nightly または Chrome が、デスクトップでもモバイルでも、正しい選択となります。
すべての組み立てが完了したら、 simple A-Frame demo にアクセスすると、シーンがレンダリングされるか、右下のボタンを押して VR 表示モードに入ることができるかどうかで、セットアップによって WebVR が正しく動作するかどうかをテストすることができます。
新しい JavaScript コードの束を理解する必要なく、WebVR 互換の 3D シーンをすばやく作成したい場合は、A-Frame が断然最適なオプションと言えます。しかし、これは生の WebVR API がどのように動作するのかを教えてはくれませんので、次に取りかかるのはこの点です。
WebVR API がどのように動作するのかを説明するために、次のような raw-webgl-example を勉強してみましょう。
メモ: このデモのソースコード は GitHub で、ライブで見ることができます also.
メモ: ブラウザーで WebVR が動作しない場合、グラフィックカードを通して実行しているかどうかを確認する必要がある場合があります。例えば NVIDIA のカードの場合、 NVIDIA コントロールパネルが正常に設定されていれば、利用できるコンテキストメニューオプションがあります - Firefox を右クリックし、 Run with graphics processor > High-performance NVIDIA processor を選んでください。
このデモでは、WebGL のデモの聖杯である、回転する 3D 立方体を扱っています。私たちはこれを生の WebGL API コードを使用して実装しています。基本的な JavaScript や WebGL は一切教えず、WebVR の部分のみを教える予定です。
このデモでは、次のような機能も備えています。
このデモのメインの JavaScript ファイルのソースコードを見ていくと、先行するコメントで "WebVR" という文字列を探せば、簡単に WebVR に特化した部分を見つけることができます。
メモ: 基本的な JavaScript と WebGL については、 JavaScript 学習素材、WebGL チュートリアルを参照してください。
この点で、コードの WebVR 部分がどのように動作するのかを見ていきましょう。
典型的な(単純な) WebVR アプリはこのように作業します。
下記の節では、この raw-webgl-demo を詳しく見ていき、上記の機能が具体的にどこで使用されるかを見ていきます。
最初に出会う WebVR 関連のコードは、以下のブロックです。
これらについて簡単に説明します。
コード内の主要な関数の一つは start() で、本体の読み込みが完了したときにこの関数を実行しています。
まず始めに、start() は WebGL コンテキストを取得して、3D グラフィックを HTML の <canvas> 要素にレンダリングするために使用します。次に、gl コンテキストが利用できるかどうかを調べます。利用できる場合は、表示するシーンを設定するためにいくつかの関数を実行します。
次に、キャンバスをブラウザーのビューポートいっぱいに設定し、レンダリングループ (drawScene()) を最初に実行して、シーンをキャンバスに実際にレンダリングする処理を始めます。これは WebVR ではない、通常のレンダリングループです。
これで最初の WebVR 固有のコードに入ります。まず最初に、 Navigator.getVRDisplays が存在するかどうかを調べます - これは API へのエントリーポイントであり、したがって WebVR の基本的な機能を適切に検出することができます。ブロックの最後(else 句の中)に、これが存在しない場合、 WebVR 1.1 がブラウザーで対応していないことを示すメッセージをログ出力していることがわかります。
if () { } ブロックの中で、 Navigator.getVRDisplays() という関数を実行しています。この関数は、コンピューターに接続されているすべての VR ディスプレイ機器を格納した配列で履行されるプロミスを返します。 1 台も接続されていない場合は、配列は空になります。
プロミスの then() ブロックの中で、配列の長さが 0 以上かどうかを調べます。0 以上であれば、変数 vrDisplay の値を配列の 0 番目のインデックスに集合させます。これで vrDisplay には、接続されたディスプレイを表す VRDisplay オブジェクトが格納されました。
メモ: コンピューターに複数の VR ディスプレイを保有することはまずないでしょうし、このデモでは単純なものなので、とりあえずはこれで大丈夫でしょう。
これで VRDisplay オブジェクトを取得し、このオブジェクトを使用してさまざまなことを行うことができます。次に行うことは、ディスプレイへの WebGL コンテンツの表示を始めたり、止めたりするための機能を設定することです。
前のコードブロックに引き続き、今度は開始/停止ボタン (btn) にイベントリスナーを追加します。このボタンがクリックされたときに、ディスプレイにすでに表示されているかどうかを確認します(これはかなり間抜けな方法で、ボタン textContent が何を格納しているかを調べることによって行われます)。
ディスプレイがまだ表示されていない場合、 VRDisplay.requestPresent() メソッドを使用して、ブラウザーがディスプレイへのコンテンツの表示を始めるようにリクエストします。これは、引数として、ディスプレイに表示したいレイヤーを表す VRLayerInit オブジェクトの配列を取ります。
現在、表示できるレイヤーの最大数は 1 で、必要なオブジェクトのメンバーは VRLayerInit.source プロパティ(これは、そのレイヤーで表示したい <canvas> への参照です。他の引数は、感覚的な既定値として与えられています - leftBounds および rightBounds)) で、引数は [{ source: canvas }] になっています。]
requestPresent() は表示が正常に始まったときに履行されるプロミスを返します。
表示リクエストが成功したので、今度は VRDisplay に表示しているコンテンツをレンダリングするための設定を始めたいと思います。最初の設定として、キャンバスで VR ディスプレイと同じ大きさに設定します。これは、VRDisplay.getEyeParameters() を使用して両目の VREyeParameters を取得することによって行われます。
次に、単純な計算を行って、目の VREyeParameters.renderWidth と VREyeParameters.renderHeight に基づいて VRDisplay 描画領域の合計幅を計算します。
次に、前回 drawScene() 関数内の Window.requestAnimationFrame() 呼び出しによって設定されたアニメーションのループをキャンセルし、代わりに drawVRScene() を呼び出すことにします。この関数は前と同じシーンをレンダリングしますが、WebVR の特別なマジックが行われます。ここでのループは WebVR の特別な VRDisplay.requestAnimationFrame メソッドによって維持されています。
最後に、ボタンテキストを更新し、次にボタンが押された時刻に VR ディスプレイへの表示を停止するようにします。
続いてボタンが押されたときに VR 表示を停止するために、 VRDisplay.exitPresent() を呼び出しています。また、ボタンのテキストコンテンツを反転させ、 requestAnimationFrame の呼び出しを入れ替えました。ここで、 VRDisplay.cancelAnimationFrame を使用して VR レンダリングのループを停止し、 drawScene() を使用して通常のレンダリングループを再び開始していることが分かります。
プレゼンテーションを始めるには、ブラウザーに表示される立体視を確認します。
実際にどのように立体視が行われるかは下記をご覧ください。
これは良い質問です。なぜなら、 VR ディスプレイ内でスムーズなレンダリングを行うには、コンピューターのリフレッシュレートではなく、ディスプレイのネイティブリフレッシュレートでコンテンツをレンダリングする必要があるからです。 VR ディスプレイのリフレッシュレートは PC のリフレッシュレートよりも大きく、通常は最大で 90fps です。このレートは、コンピューターのコアリフレッシュレートとは異なる形になります。
VR ディスプレイが表示されていないときは、VRDisplay.requestAnimationFrame は Window.requestAnimationFrame と同じように動作するので、必要に応じて、このアプリで使用している 2 つのレンダリング ループではなく、1 つのレンダリング ループだけを使用できることに留意してください。2 つ使用したのは、VR ディスプレイが存在するかどうかに応じて異なることを行い、理解しやすいように物事を別個のものにしたかったからです。
この点で、 VR ハードウェアにアクセスし、ハードウェアにシーンを表示するようリクエストし、レンダリング ループを実行し始めるために必要なすべてのコードを見てきました。これで、レンダリング ループのコードを見て、 WebVR 固有の部分がどのように動作するのかを説明します。
まずすべて、レンダリングループ関数である drawVRScene() の定義から始めます。この内部で最初に行うことは VRDisplay.requestAnimationFrame() を呼び出して、ループが一度呼ばれた後(これはコードの前半で VR ディスプレイに表示を開始したときに発生します)、ループを実行し続けるようにすることです。この呼び出しをグローバル変数 vrSceneFrame の値として設定し、VR プレゼンテーションを終了したら VRDisplay.cancelAnimationFrame() の呼び出しでループをキャンセルできるようにしています。
次に VRDisplay.getFrameData() を呼び出して、フレームデータを格納するために使用したい変数名を渡します。先ほど、frameDataという変数で初期化しました。呼び出された後、この変数には次のフレームを VR 機器にレンダリングするために必要なデータが VRFrameData オブジェクトとしてパッケージングされて格納されます。これには、左目用と右目用のシーンを正しくレンダリングするための投影およびビューマトリックス、そして方向や位置などVRディスプレイのデータを格納する現在の VRPose オブジェクトといったものが含まれています。
これは、レンダリングされたビューが常に最新の状態になるように、フレームごとに呼び出される必要があります。
これで、VRPose プロパティから現在の VRFrameData.pose を取得し、後で使用するために位置と方向を格納し、変数 poseStatsDisplayed が true の場合は現在の pose を pose stats ボックスに送って表示することができました。
これで、キャンバスには描画を始める前にクリアされ、次のフレームがはっきりと見えるようになり、前回のレンダリングフレームも見えなくなりました。
これで、左目と右目の両方のビューをレンダリングすることができます。最初に、レンダリングに使用する投影位置と表示位置を作成する必要があります。これらは WebGLUniformLocation オブジェクトで、 WebGLRenderingContext.getUniformLocation() メソッドを使用して作成し、引数としてシェーダープログラムの識別子と識別名 を渡します。
次のレンダリング手順では、次のことを行います。
これで、まったく同じことを右目で行います。
次に、 drawGeometry() 関数を定義します。この関数のほとんどは、 3D 立方体を描画するために必要な一般的な WebGL コードです。 mvTranslate() と mvRotate() 関数呼び出しに WebVR 固有の部分があります。これらは、現在のフレームにおける立方体の移動と回転を定義する行列を WebGL プログラムに渡すものです。
これらの値を VRPose オブジェクトから取得した VR ディスプレイの位置 (curPos) と方向 (curOrient) によって変更していることがわかると思います。その結果、例えば頭を左に動かしたり回転させたりすると、x 位置値 (curPos[0]) と y 回転値 ([curOrient[1]) が x 移動値に追加されます。つまり、何かを見ているときに頭を左に移動/回転させると、キューブは右に移動することを意味します。
これは、VR ポーズデータを使用するためのすばやく汚い方法ですが、基本的な原理を説明しています。
次のコードは WebVR とは何の関係もなく、各フレームで立方体の回転を更新するだけです。
レンダリングループの最後の部分で VRDisplay.submitFrame() を呼び出します。このメソッドでは、すべての作業が完了し、 <canvas> に表示がレンダリングされると、フレームを VR ディスプレイに送信して、そこに表示することができます。
この節では、各フレームで更新されたポーズデータを表示する displayPoseStats() 関数について説明します。この関数はかなり単純です。
すべて VRPose オブジェクトから得られる 6 つの異なる形のプロパティ値を自分自身で変数に格納します。それぞれ Float32Array とします。
そして、そのデータを情報ボックスに書き出し、フレームごとに更新しています。そうしないと値が読みにくいので、 toFixed() で各値を小数点以下 3 桁に固定しています。
データを表示する前に、線形加速度と角加速度の配列が正常に返されたかどうかを検出するために、条件式を使用していることにメモしておいてください。これらの値はまだほとんどの VR ハードウェアで報告されないので、これを行わないとコードがエラーを発生します(配列は正常に報告されないと null を返します)。
WebVR の仕様では、 VR ディスプレイの状態の変化にアプリのコードが反応できるように、いくつかのイベントが発行される機能があります (Window イベント を参照してください)。例として、
これらがどのように動作するのかを示すために、この単純なデモでは以下のような例を記載しています。
このプロパティには、イベントが発行された VRDisplay への参照が格納され、イベントが発生した理由を人間が読み取り可能な値で示します。
これはとても有益なイベントです。ディスプレイが予期せず切断された場合を処理するために使用することができ、エラーが発生するのを阻止し、ユーザーに状況を認識させることができます。 Google の Webvr.info プレゼンテーションのデモでは、このイベントを使用して onVRPresentChange() function が実行され、UI コントロールが適宜更新されてキャンバスのサイズが変更されます。
この記事では、単純な WebVR 1.1 アプリを作成する方法について、取得するのに役立つ、ごく基本的なことを説明しました。
This page was last modified on 2025年7月22日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.