WebXR デバイス API

W3C 勧告候補草案,

この文書の詳細
このバージョン:
https://www.w3.org/TR/2026/CRD-webxr-20260609/
最新公開バージョン:
https://www.w3.org/TR/webxr/
編集者草案:
https://immersive-web.github.io/webxr/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/webxr/
実装レポート:
https://wpt.fyi/results/webxr?label=master&label=experimental&aligned
フィードバック:
GitHub
編集者:
(Google)
(Google [2020年まで Mozilla])
(Meta)
元編集者:
(Amazon [2018年まで Microsoft])
参加:
課題を提出 (未解決の課題)
メーリングリストアーカイブ
W3C の #immersive-web IRC

概要

この仕様は、センサーやヘッドマウントディスプレイを含む、仮想現実(VR)および拡張現実(AR)デバイスへの Web 上でのアクセスのサポートについて説明する。

この文書のステータス

この節は、公開時点におけるこの文書のステータスについて説明する。現在の W3C 公開文書の一覧およびこの 技術レポートの最新改訂版は、W3C 標準および草案インデックスで確認できる。

Immersive Web Working Group は、グループがまだ対処していない すべてのバグ 報告の一覧を管理している。この草案では、作業部会でまだ議論される予定の保留中の課題の一部を強調している。 これらの課題の結果については、それらが有効であるかどうかを含め、いかなる決定も行われていない。 未解決の課題に対する仕様テキスト案を含むプルリクエストは強く推奨される。

この文書は、Immersive Web Working Group により、勧告 トラックを用いた勧告候補草案として公開された。この文書は W3C 勧告となることを意図している。

勧告候補としての公開は、 W3C およびそのメンバーによる承認を意味しない。 勧告候補草案は、作業部会が後続の勧告候補スナップショットに含める予定の、 以前の勧告候補からの変更を統合する。 これは草案文書であり、いつでも他の文書により更新、置換、または廃止される可能性がある。 この文書を作業中のもの以外として引用することは不適切である。

この文書が勧告案段階へ進むための入口基準は、 この仕様のすべての機能を実装する、少なくとも 2 つの独立した相互運用可能なユーザーエージェントが存在することであり、 これは作業部会が開発したテストスイートで定義されるユーザーエージェントテストに合格することにより判断される。 作業部会は進捗を追跡するための実装レポートを作成する。

この文書は、 W3C 特許ポリシーの下で運営されるグループによって作成された。 W3C は、グループの成果物に関連して行われたあらゆる特許 開示の公開リストを管理している。そのページには、特許を開示するための手順も含まれている。 個人が、当該個人が 必須 クレームを含むと考える特許について実際の知識を有する場合、その情報を W3C 特許ポリシー第 6 節に従って開示しなければならない。

この文書は、2025年8月18日 W3C プロセス文書に準拠する。

前回の草案からの変更については、 変更の節を参照。

1. はじめに

仮想現実(VR)および拡張現実(AR)アプリケーションを可能にするハードウェアは、今や消費者に広く 利用可能であり、新たな機会と課題の両方を備えた没入型コンピューティングプラットフォームを提供している。 没入型ハードウェアと直接やり取りする能力は、この環境において Web が第一級市民として動作するための備えを 十分に持つことを保証するうえで不可欠である。

没入型コンピューティングは、許容可能な体験を提供するために、高精度かつ低遅延の通信に対する厳格な要件を 導入する。また、Web のようなプラットフォームに固有のセキュリティ上の懸念ももたらす。 WebXR Device API は、開発者が多種多様なハードウェアフォームファクターにわたり、Web 上で魅力的で快適かつ 安全な没入型アプリケーションを構築できるようにするために必要なインターフェースを提供する。

RelativeOrientationSensorAbsoluteOrientationSensor などの他の Web インターフェースは、一部のデバイスからの入力を表面化して、限定的な状況で WebXR Device API を ポリフィルするために転用できる。しかし、これらのインターフェースは、6DoF トラッキング、ヘッドセット周辺機器への表示、またはトラッキングされる入力デバイスなど、ハイエンドな没入型体験の 複数の機能をサポートできない。

1.1. 用語

この文書では、仮想現実、拡張現実、およびその他の関連技術に用いられるハードウェア、アプリケーション、 技法の範囲を指すために、全体を通して頭字語 XR を使用する。例には次が含まれるが、 これらに限定されない:

それらに共通する重要な点は、仮想コンテンツのビューをシミュレートするために、ある程度の空間トラッキングを 提供することである。

"XR device"、"XR application" などの用語は、一般に上記のいずれにも適用されるものと理解される。 この文書のうち、これらのデバイスの一部にのみ適用される部分は、必要に応じてその旨を示す。

3DoF および 6DoF という用語は、XR devices のトラッキング能力を説明するために、この文書全体で使用される。

1.2. アプリケーションフロー

WebXR Device API を使用するほとんどのアプリケーションは、類似した使用パターンに従う:

2. モデル

2.1. XR device

XR device は、 没入型コンテンツをユーザーに提示できる物理的なハードウェア単位である。コンテンツは、ユーザー環境のさまざまな 側面をシミュレートまたは拡張する視覚、音声、触覚、その他の感覚出力を生成する場合に "immersive" であると見なされる。最も頻繁には、これはユーザーの空間内での動きを追跡し、 ユーザーの動きに同期した出力を生成することを伴う。デスクトップクライアントでは、通常これは ヘッドセット周辺機器である。モバイルクライアントでは、ビューアーハーネスと組み合わせたモバイルデバイス自体を 表す場合がある。また、ステレオ表示機能を持たないが、より高度なトラッキングを備えたデバイスを表す場合もある。

XR device は、サポートされる modes のリストlist of strings)を持ち、これはその 含む XRSessionMode の列挙値のうち、その XR device がサポートするものを含む。

XR device は、その list of supported modes 内の各 XRSessionMode について set of granted features を持ち、これは setfeature descriptors であり、最初は空の set でなければならない。

ユーザーエージェントは、list of immersive XR devicesXR devicelist)を持ち、これは最初は空の list で なければならない。

ユーザーエージェントは、immersive XR devicenull または XR device)を持ち、これは最初は null であり、 list of immersive XR devices からのアクティブな XR device を表す。このオブジェクトは 別スレッド上に存在し、非同期に更新されてもよい。

ユーザーエージェントは、default inline XR device を持たなければならず、これは XR device であり、その list of supported modes"inline"contain しなければならない。 default inline XR device は、いかなるポーズ情報も報告してはならず、 ポインターイベントによって作成されたもの以外の XR input source やイベントを報告してはならない。

注: default inline XR device は純粋に開発者の便宜のために存在し、インラインコンテンツと没入型コンテンツの両方で同じレンダリングおよび入力ロジックを 使用できるようにする。default inline XR device は、ページ上の他の仕組み (入力用のポインターイベントなど)を通じて開発者がすでに利用可能な情報以外の情報を公開せず、 それらの値を XR 中心の形式で表面化するだけである。

ユーザーエージェントは、inline XR device を持たなければならず、これは XR device であり、その list of supported modes"inline"contain しなければならない。 inline XR device は、サポートされる primary views を HTML 文書の一部として 公開できる場合、inline-stereo feature descriptorcapable of supporting してもよい。 inline XR device は、それが提供するトラッキングをインラインコンテンツに 公開することに意味がある場合は immersive XR device であってもよく、 そうでない場合は default inline XR device であってもよい。

注: 電話では、inline XR device は、ジャイロスコープや 加速度計など、電話の内部センサーから導出されたポーズ情報を報告する場合がある。同様のセンサーを持たないデスクトップや ラップトップでは、inline XR device はポーズを報告できず、そのため default inline XR device にフォールバックすべきである。 ユーザーエージェントがすでに XR device 上で実行されている場合、inline XR device は 同じデバイスとなり、複数の views をサポートする場合がある。default inline XR device が公開するものを超えるトラッキングまたは入力機能が 提供される前に、ユーザーの同意が与えられなければならない。

list of immersive XR devicesinline XR device、および immersive XR device の現在値は、別スレッド上に存在し、非同期に更新されてもよい。これらのオブジェクトは、 in parallel で実行されていない手順で直接アクセスすべきではない。

3. 初期化

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute XRSystem xr;
};

xr 属性の getter は、それに関連付けられている XRSystem オブジェクトを 返さなければならない。

3.2. XRSystem

[SecureContext, Exposed=Window] interface XRSystem : EventTarget {
  // Methods
  Promise<boolean> isSessionSupported(XRSessionMode mode);
  [NewObject] Promise<XRSession> requestSession(XRSessionMode mode, optional XRSessionInit options = {});

  // Events
  attribute EventHandler ondevicechange;
};

ユーザーエージェントは、Navigator オブジェクトが作成されるときに XRSystem オブジェクトを作成し、 そのオブジェクトに関連付けなければならない。

XRSystem オブジェクトは API への入口であり、ユーザーエージェントで利用可能な XR 機能を問い合わせ、 XRSession の作成を通じて XR ハードウェアとの通信を開始するために使用される。

ユーザーエージェントは、システムに接続された没入型 XR デバイスを enumerate immersive XR devices できなければならず、 その時点で利用可能な各デバイスは list of immersive XR devices に配置される。列挙を要求する後続のアルゴリズムは、キャッシュされた list of immersive XR devices を再利用しなければならない。デバイスの列挙は device tracking を初期化すべきではない。 最初の列挙後、ユーザーエージェントはデバイスの接続および切断の監視を開始し、接続されたデバイスを list of immersive XR devices に追加し、切断されたデバイスを削除しなければならない。

list of immersive XR devices が変化するたびに、 ユーザーエージェントは次の手順を実行して select an immersive XR device すべきである:

  1. oldDeviceimmersive XR device とする。

  2. list of immersive XR devices が空の list である場合、immersive XR devicenull に設定する。

  3. list of immersive XR devicessize が 1 の場合、immersive XR devicelist of immersive XR devices[0] に設定する。

  4. immersive XR device を次のように設定する:

    アクティブな XRSession が存在し、 list of immersive XR devicesoldDevicecontains する場合:

    immersive XR deviceoldDevice に設定する。

    それ以外の場合:

    immersive XR device を、ユーザーエージェントが選択する デバイスに設定する。

  5. ユーザーエージェントは、適切な場合は inline XR deviceimmersive XR device に更新し、 そうでない場合は default inline XR device に更新してもよい。

  6. これが初めてデバイスが列挙された場合、または oldDeviceimmersive XR device と等しい場合、これらの手順を中止する。

  7. アクティブな XRSession をすべて シャットダウンする。

  8. すべての WebGLRenderingContextBase インスタンスの XR compatible 真偽値を false に設定する タスクをキューに入れる

  9. 関連する Global objectnavigatorxr 上で、devicechange という名前のイベントを 発火する タスクをキューに入れる

  10. タスクをキューに入れてimmersive XR device または inline XR device の変更の影響を受ける任意の XRPermissionStatus オブジェクト上で、適切な change イベントを発火する。

注: これらの手順は常に in parallel で実行されるべきである。

注: ユーザーエージェントは、 list of immersive XR devices が複数のデバイスを含む場合に select an immersive XR device するため、望む任意の基準を 使用することが許される。たとえば、ユーザーエージェントは常にリストの最初の項目を選択してもよく、またはユーザーが デバイスの優先度を管理できる設定 UI を提供してもよい。理想的には、既定のデバイスを選択するために使用される アルゴリズムは安定しており、複数のブラウジングセッションにわたって同じデバイスが選択される結果となる。

ユーザーエージェントは、次の手順を実行して ensure an immersive XR device is selected できる:

  1. immersive XR devicenull でない場合、 immersive XR device を返し、これらの手順を中止する。

  2. Enumerate immersive XR devices

  3. Select an immersive XR device

  4. immersive XR device を返す。

注: これらの手順は常に in parallel で実行されるべきである。

ondevicechange 属性は、 devicechange イベント型に対する イベントハンドラー IDL 属性である。

isSessionSupported(mode) メソッドは、 指定された mode がユーザーエージェントおよびデバイス機能によってサポートされる可能性があるかどうかを 問い合わせる。

このメソッドが呼び出されたとき、次の手順を実行しなければならない:

  1. promise を、この XRSystem関連するレルム内の 新しい Promise とする。

  2. mode"inline" である場合、promisetrue解決し、それを返す。

  3. mode没入型セッションモードであり、要求元文書の origin が "xr-spatial-tracking" permissions policy の使用を許可されていない場合、 promise を "SecurityError" DOMException拒否し、それを返す。

  4. セッション mode がサポートされるかどうかを次のように確認する:

    ユーザーエージェントおよびシステムが mode セッションを never support することが分かっている場合

    promisefalse解決する。

    ユーザーエージェントおよびシステムが mode セッションを usually support することが分かっている場合

    ユーザーエージェント文字列によって識別不能なこのユーザーエージェントのすべての インスタンスがここで同じ結果を生成する場合に限り、promisetrue解決されてもよい。

    それ以外の場合

    次の手順を in parallel で実行する:

    1. device を、mode、空の list、 および空の list について 現在のデバイスを取得する結果とする。

    2. device が null の場合、promisefalse解決し、これらの手順を中止する。

    3. devicelist of supported modesmodecontain しない場合、promisefalse解決する タスクをキューに入れ、これらの手順を中止する。

    4. modemode と等しい XRSessionSupportedPermissionDescriptor を用いて、"xr-session-supported" 強力な機能を使用する許可を要求する。それが "denied" を返す場合、promisefalse解決する タスクをキューに入れ、これらの手順を中止する。 詳細についてはフィンガープリンティング上の考慮事項を参照。

    5. promisetrue解決する タスクをキューに入れる

  5. promise を返す。

注: isSessionSupported() の目的は、ユーザーエージェントが XRSession を作成できる能力を 完全な精度で報告することではなく、指定されたモードのセッションを作成する能力を提示することが推奨されるかどうかを ページに知らせることである。ユーザーエージェントが、メソッドを解決する前に必要なハードウェア/ソフトウェアの存在を 確認する場合であっても、一定程度の偽陽性は想定される。(たとえば、適切なハードウェアが存在していても、 セッションが要求された時点で別のアプリケーションに排他的アクセスを与えている場合がある。)

XR コンテンツを含むほとんどのページは、文書ライフサイクルの早い段階で isSessionSupported() を呼び出すことが期待される。そのため、isSessionSupported() の呼び出しは、モーダルまたはその他の侵入的な UI の表示を避けるべきである。isSessionSupported() の呼び出しは、デバイス選択 UI を起動してはならず、システム上で実行中の XR アプリケーションに干渉してはならず、 システムトレイやストアフロントなどの XR 関連アプリケーションを起動させてはならない。

次のコードは、immersive-vr セッションがサポートされているかどうかを確認する。
const supported = await navigator.xr.isSessionSupported('immersive-vr');
if (supported) {
  // 'immersive-vr' セッションはサポートされる可能性がある。
  // ページはユーザーにサポートを提示すべきである。
} else {
  // 'immersive-vr' セッションはサポートされていない。
}

XRSystem オブジェクトは、pending immersive session 真偽値を持ち、これは最初は false でなければならない。また active immersive session を持ち、これは最初は null で なければならない。さらに list of inline sessions を持ち、これは最初は空でなければならない。

requestSession(mode, options) メソッドは、可能であれば指定された mode について XRSession の初期化を試み、必要であれば没入モードに入る。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. promise を、このメソッドが呼び出された XRSystem関連するレルム内の 新しい Promise とする。

  2. mode没入型セッションモードである場合は immersivetrue とし、それ以外の場合は false とする。

  3. global object を、このメソッドが呼び出された XRSystem に対する 関連する Global object とする。

  4. セッション要求が許可されるかどうかを次のように確認する:

    immersivetrue の場合:
    1. global object についてimmersive session request is allowed かどうかを確認し、許可されない場合は promise を "SecurityError" DOMException拒否し、promise を返す。

    2. pending immersive sessiontrue であるか、または active immersive sessionnull でない場合、promise を "InvalidStateError" DOMException拒否し、promise を返す。

    3. pending immersive sessiontrue に設定する。

    それ以外の場合:

    global object についてinline session request is allowed かどうかを確認し、許可されない場合は promise を "SecurityError" DOMException拒否し、 promise を返す。

  5. 次の手順を in parallel で実行する:

    1. requiredFeatures を、optionsrequiredFeatures とする。

    2. optionalFeatures を、optionsoptionalFeatures とする。

    3. device を、moderequiredFeatures、 および optionalFeatures について 現在のデバイスを取得する結果に設定する。

    4. 次の手順を実行するためにタスクをキューに入れる:

      1. devicenull であるか、または devicelist of supported modesmodecontain しない場合、次の手順を実行する:

        1. promise を "NotSupportedError" DOMException拒否する。

        2. immersivetrue の場合、 pending immersive sessionfalse に設定する。

        3. これらの手順を中止する。

      2. descriptor を、moderequiredFeatures、 および optionalFeatures で初期化された XRPermissionDescriptor とする

      3. statusXRPermissionStatus とし、最初は null とする

      4. descriptor および status を用いて xr permission を要求する

      5. statusstate"denied" である場合、次の手順を実行する:

        1. promise を "NotSupportedError" DOMException拒否する。

        2. immersivetrue の場合、 pending immersive sessionfalse に設定する。

        3. これらの手順を中止する。

      6. granted を、statusgranted から取得される set とする。

      7. session を、この XRSystem関連するレルム内の 新しい XRSession オブジェクトとする。

      8. sessionmodegranted、および device を用いて セッションを初期化する

      9. active immersive session を 潜在的に次のように設定する:

        immersivetrue の場合:

        active immersive sessionsession に設定し、pending immersive sessionfalse に設定する。

        それ以外の場合:

        sessionlist of inline sessions に追加する。

      10. promisesession解決する。

      11. 次の手順を実行するためにタスクをキューに入れる:

        注: これらの手順により、初期 inputsourceschange イベントが、初期セッションの解決後に発生することが保証される。
        1. sessionpromise resolved フラグを true に設定する。

        2. sources を、session に接続されている既存の任意の入力ソースとする。

        3. sources が空でない場合、次の手順を実行する:

          1. sessionlist of active XR input sourcessources に設定する。

          2. XRInputSourcesChangeEvent を、session 上で inputsourceschange という名前で発火し、addedsources に設定する。

  6. promise を返す。

XRSessionMode moderequiredFeatures、および optionalFeatures について obtain the current device するには、ユーザーエージェントは次の手順を実行しなければならない:

  1. device を次のように選択する:

    mode没入型セッションモードである場合:

    device を、ensuring an immersive XR device is selected の結果に設定する。

    そうではなく、requiredFeatures または optionalFeatures が空でない場合:

    deviceinline XR device に設定する。

    それ以外の場合:

    devicedefault inline XR device に設定する。

  2. device を返す。

注: これらの手順は常に in parallel で実行されるべきである。

次のコードは、immersive-vr XRSession を取得しようとする。
const xrSession = await navigator.xr.requestSession("immersive-vr");

3.3. XRSessionMode

XRSessionMode enum は、XRSession が 動作できるモードを定義する。

enum XRSessionMode {
  "inline",
  "immersive-vr",
  "immersive-ar"
};

この文書では、inline session という用語は inline セッションを指し、immersive session という用語は immersive-vr または immersive-ar セッションのいずれかを指す。

Immersive sessions は ある程度の viewer トラッキングを提供しなければならず、 コンテンツはユーザーおよび/または周囲の環境に対して適切なスケールで表示されなければならない。さらに、 Immersive sessions は、immersive XR device への exclusive access を与えられなければならない。これは、immersive session"visible" である間、HTML 文書は immersive XR device のディスプレイに表示されず、他のいかなるソースからの コンテンツも排他的アクセスを持たないことを意味する。ただし Exclusive access は、ユーザーエージェントが独自の UI を重ねることを妨げない。 ただし、この UI は最小限であるべきである。

注: UA は、代替入力ソースがない場合に、 ガーディアン境界、障害物、またはユーザーの手など、アクセシビリティや安全性のためのコンテンツを重ねることを 選択してもよい。

注: 将来の仕様またはモジュールは、 immersive session の定義を拡張して、追加のセッションモードを含める可能性がある。

注: exclusive access を提示する方法の例には、 仮想現実ヘッドセットに表示されるステレオコンテンツが含まれる。

注: 重ね合わせられた UI の例として、ユーザーエージェントまたは オペレーティングシステムは、immersive session 内で、レンダリングされたコンテンツ上に通知を表示する場合がある。

注: immersive XR device のディスプレイには immersive session 中に HTML 文書は表示されないが、別のディスプレイ上には表示される場合がある。 たとえば、ユーザーがコンピューター上の 2D ブラウザーから、接続された immersive session に入る場合である。 immersive XR device

3.4. 機能の依存関係

XRSession の一部の機能は、 さまざまな理由で普遍的に利用できるとは限らない。その理由の一つは、すべての XR デバイスが機能の完全なセットを サポートできるわけではないという事実である。別の考慮事項は、一部の機能が機微情報を公開し、機能する前に ユーザー意図の明確な信号を必要とする 可能性があることである。

基盤となる XR プラットフォームを初期化して XRSession を作成した直後に、 アプリケーションが正しく機能できないことをユーザーに通知するのは望ましくないユーザー体験であるため、開発者は requestSession()XRSessionInit 辞書を渡すことにより、required features を示すことができる。 これにより、デバイスの制限により、または機能に関連する機微情報を公開する ユーザー意図の明確な信号がないために、 required features のいずれかが利用できない場合、XRSession の作成が ブロックされる。

さらに、開発者は、より高機能なデバイス上で実行されるときに機能を段階的に強化する体験を設計することが推奨される。 その体験が必須とはしないが、利用可能な場合に活用する Optional features も、必要に応じて機能を有効化する前に ユーザー意図を判断できるように、 XRSessionInit 辞書で示されなければならない。

dictionary XRSessionInit {
  sequence<DOMString> requiredFeatures;
  sequence<DOMString> optionalFeatures;
};

requiredFeatures 配列は、その体験の任意の Required features を含む。 リスト内の値が認識される feature descriptor でない場合、 XRSession は作成されない。 requiredFeatures 配列に列挙された機能のいずれかが XR device によってサポートされない場合、または必要な場合に ユーザー意図の明確な信号を受け取っていない場合、 XRSession は作成されない。

optionalFeatures 配列は、その体験の任意の Optional features を含む。 リスト内の値が認識される feature descriptor でない場合、それは無視される。 optionalFeatures 配列に列挙された機能は、XR device によってサポートされ、必要な場合に ユーザー意図の明確な信号が与えられた場合に 有効化されるが、存在しない場合でも XRSession の作成を ブロックしない。

機能リストに与えられる値は、値が次のいずれかである場合、有効な feature descriptor と見なされる:

この仕様の将来の反復および追加モジュールは、受け入れられる feature descriptors のリストを拡張する可能性がある。

注: 機能が追加の初期化を必要とする場合、 XRSessionInit はその機能のための新しいフィールドで拡張されるべきである。

要求された XRSessionMode に応じて、特定の feature descriptors が、既定で requiredFeatures または optionalFeatures リストに追加される。次の表は、各セッション型および機能リストに関連付けられた default features を説明する:

機能 セッション リスト
"viewer" すべてのセッション requiredFeatures
"local" Immersive sessions requiredFeatures

requiredFeatures および optionalFeatures によって与えられる feature descriptors の結合リストは、まとめて XRSessionrequested features と見なされる。

requested features リストに存在する一部の feature descriptors は、permissions policy および/または、その機能を使用する ユーザー意図が、明示的な同意 または 暗黙的な同意のいずれかを通じて 十分に理解されることを要求する要件の対象となる。次の表は、有効化される前に満たされなければならない feature requirements を説明する:

機能 Permissions Policy 必須 同意必須
"local" "xr-spatial-tracking" Inline sessions は同意を必要とする
"local-floor" "xr-spatial-tracking" 常に同意を必要とする
"bounded-floor" "xr-spatial-tracking" 常に同意を必要とする
"unbounded" "xr-spatial-tracking" 常に同意を必要とする

注: "local" は、default feature として immersive sessionsrequested features に常に含まれる。そのため immersive sessions は常に 明示的な同意または 暗黙的な同意を取得する必要がある。

inline-stereo feature descriptor は、 inline session が インライン表示用のステレオ primary views を公開することを要求する。有効化された場合、list of views は 2 つの primary views を含まなければならず、一方は eye"left" であり、もう一方は eye"right" である。

inline-stereo feature descriptor は、 "inline" セッションにのみ適用される。これは immersive sessions に付与されてはならない。

Requested features は、XR device がその機能を capable of supporting する場合にのみ、セッションで有効化できる。 これは、現在の構成がその機能をサポートすることをまだ検証していない場合でも、その機能が何らかの構成で XR device によってサポートされることが分かっていることを意味する。 ユーザーエージェントは、より一貫したユーザー体験を得るために、望むならより厳格な制約を適用してもよい。

注: たとえば、いくつかの VR デバイスは、 ユーザーがその範囲内を動き回るための安全境界の構成、または境界構成を省略してユーザーがその場に立つことを 想定するモードでの動作のいずれかをサポートしている。そのようなデバイスは、現在安全境界が構成されていなくても、 "bounded-floor" XRReferenceSpacecapable of supporting すると見なせる。これは、その体験が要求する場合、ユーザーがデバイスを適切に構成できると期待されるためである。 これは、望むならユーザーエージェントが、requested features を解決する前に XR device を完全に初期化したり、ユーザーの環境が認識されるのを待ったりすることを 避けられるようにするためである。しかし、追加の初期化なしにセッション要求時点の境界状態をユーザーエージェントが 知っている場合、安全境界がすでに構成されていなければ "bounded-floor" 機能を拒否することを選択してもよい。

4. セッション

4.1. XRSession

XR ハードウェアとのあらゆるやり取りは、XRSession オブジェクトを介して行われる。これは、XRSystem オブジェクト上で requestSession() を呼び出すことによってのみ取得できる。セッションが正常に取得されると、それを使用して viewer pose をポーリングし、 ユーザーの環境に関する情報を問い合わせ、ユーザーに画像を提示できる。

ユーザーエージェントは、可能な場合、XRSession が 取得されるまで、デバイストラッキングまたはレンダリング機能を 初期化すべきではない。これは、XR ハードウェアの存在を テストして XR 機能を提示したいだけのページへ最初に移動したときに、バッテリー使用量の増加や関連ユーティリティ アプリケーションの表示など、XR システムが実際には使用されていないにもかかわらず起動される望ましくない副作用を 防ぐためである。ただし、すべての XR プラットフォームがトラッキングを初期化せずにハードウェアの存在を検出する 方法を提供するわけではないため、これは強い推奨にすぎない。

enum XRVisibilityState {
  "visible",
  "visible-blurred",
  "hidden",
};

[SecureContext, Exposed=Window] interface XRSession : EventTarget {
  // Attributes
  readonly attribute XRVisibilityState visibilityState;
  readonly attribute float? frameRate;
  readonly attribute Float32Array? supportedFrameRates;
  [SameObject] readonly attribute XRRenderState renderState;
  [SameObject] readonly attribute XRInputSourceArray inputSources;
  [SameObject] readonly attribute XRInputSourceArray trackedSources;
  readonly attribute FrozenArray<DOMString> enabledFeatures;
  readonly attribute boolean isSystemKeyboardSupported;

  // Methods
  undefined updateRenderState(optional XRRenderStateInit state = {});
  Promise<undefined> updateTargetFrameRate(float rate);
  [NewObject] Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type);

  unsigned long requestAnimationFrame(XRFrameRequestCallback callback);
  undefined cancelAnimationFrame(unsigned long handle);

  Promise<undefined> end();

  // Events
  attribute EventHandler onend;
  attribute EventHandler oninputsourceschange;
  attribute EventHandler onselect;
  attribute EventHandler onselectstart;
  attribute EventHandler onselectend;
  attribute EventHandler onsqueeze;
  attribute EventHandler onsqueezestart;
  attribute EventHandler onsqueezeend;
  attribute EventHandler onvisibilitychange;
  attribute EventHandler onframeratechange;
};

XRSessionmode を持ち、これは XRSessionMode の値の 1 つである。

XRSessionanimation frame を持つ。これは、activefalse に、animationFrametrue に、そして session をその XRSession に設定して初期化された XRFrame である。

XRSessionset of granted features を持つ。これは、その XRSession に付与された feature descriptors に対応する DOMStringset である。

enabledFeatures 属性は、 set of granted features 内の機能を、新しい DOMString 配列として返す。

isSystemKeyboardSupported 属性は、 XRSystem が、 XRSession が アクティブな間にシステムキーボードを表示する能力を持つことを示す。isSystemKeyboardSupportedtrue の場合、オーバーレイキーボードを起動する Web API(focus など)は システムキーボードを表示する。XRSession は、 キーボードが表示されている間、XRSessionvisibility state"visible-blurred" に設定しなければならない。

sessionmodegranted、および device が与えられたとき、 セッションを初期化するには、 ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionmodemode に設定する。

  2. sessionXR devicedevice に設定する。

  3. sessionset of granted featuresgranted に設定する。

  4. レンダーステートを初期化する

  5. ユーザーエージェントの他の機能がまだそうしていない場合、必要なユーザーへの指示を表示することを含め、 デバイスのトラッキングおよびレンダリング機能を初期化するために必要なプラットフォーム固有の手順を実行する。

注: 一部のデバイスは、アクティベーションのために 追加のユーザー指示を必要とする。たとえば、電話ベースのヘッドセットデバイスで没入モードに入るには電話を ヘッドセットに挿入する必要があり、外部ヘッドセットに接続されたデスクトップブラウザーでそうするにはヘッドセットを 装着する必要がある。そのような指示が表示されることを保証する責任は、作者ではなくユーザーエージェントにある。

さまざまな状況が セッションをシャットダウンする可能性があり、これは恒久的で元に戻せない。 セッションがシャットダウンされると、XR device のトラッキングまたはレンダリング機能に再びアクセスする唯一の方法は、 新しいセッションを要求することである。各 XRSession は、 最初は false に設定された ended 真偽値を持ち、これはシャットダウンされたかどうかを示す。

XRSession session がシャットダウンされるとき、次の手順が実行される:

  1. sessionended 値を true に設定する。

  2. active immersive sessionsession と等しい場合、 active immersive sessionnull に設定する。

  3. sessionlist of inline sessions から削除する。

  4. end() によって返された promise を除き、session によって返された未解決の promise を InvalidStateError拒否する。

  5. ユーザーエージェントの他の機能がそれらをアクティブに使用していない場合、デバイスのトラッキングおよび レンダリング機能をシャットダウンするために必要なプラットフォーム固有の手順を実行する。これには次を 含めなければならない:

  6. session 上で XRSessionEventend という名前で発火するタスクをキューに入れる

end() メソッドは、セッションを手動でシャットダウンする方法を提供する。 呼び出されたとき、次の手順を実行しなければならない:

  1. promise を、この XRSession関連するレルム内の 新しい Promise とする。

  2. thisended 値が true である場合、promise を "InvalidStateError" DOMException拒否し、 promise を返す。

  3. thisシャットダウンする。

  4. 次の手順を実行するためにタスクをキューに入れる:

    1. セッションのシャットダウンに関連するプラットフォーム固有の手順が完了するまで待つ。

    2. promise解決する。

  5. promise を返す。

XRSession は、 新しい XRRenderState である active render state と、最初は null である XRRenderState である pending render state を持つ。

renderState 属性は、XRSessionactive render state を返す。

XRSession は、 ラジアンで定義される minimum inline field of viewmaximum inline field of view を持つ。値はユーザーエージェントによって 決定されなければならず、0 から PI の範囲内でなければならない。

XRSession は、 メートルで定義される minimum near clip planemaximum far clip plane を持つ。値はユーザーエージェントによって 決定されなければならず、非負でなければならない。minimum near clip plane0.1 未満であるべきである。maximum far clip plane1000.0 より大きいべきである(無限であってもよい)。

ユーザーエージェントが XRSession session および XRRenderStateInit newState を用いて pending layers state を更新するとき、次の手順を実行しなければならない:

  1. newStatelayers の値が null でない場合、NotSupportedError を投げる。

注: WebXR layers module は、このアルゴリズムに 新しい意味論を導入する。

ユーザーエージェントが XRSession session 上で nominal frame rate を適用する rate とき、次の手順を 実行しなければならない:

  1. ratesessioninternal nominal framerate と同じである場合、 これらの手順を中止する。

  2. sessionended 値が true である場合、これらの手順を中止する。

  3. sessioninternal nominal frameraterate に設定する。

  4. session 上で、XRSessionEvent イベントを frameratechange という名前で発火する。

updateTargetFrameRate(rate) メソッドは、target frame rate rateXRSession に渡す。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionthis とする。

  2. promise を、session関連するレルム内の 新しい Promise とする。

  3. sessioninternal nominal framerate を持たない場合、 promise を "InvalidStateError" DOMException拒否し、promise を返す。

  4. sessionended 値が true である場合、 promise を "InvalidStateError" DOMException拒否し、 promise を返す。

  5. ratesupportedFrameRates に含まれない場合、promise を "TypeError" DOMException拒否し、promise を返す。

  6. sessioninternal target frameraterate に設定する。

  7. 次の手順を実行するためにタスクをキューに入れる:

    1. XR Compositor は、rate を使用して新しい display frame rate および/または nominal frame rate を計算してもよい。

    2. newrate を新しい nominal frame rate とする。

    3. 次の手順を実行するためにタスクをキューに入れる:

      1. XRSystemnominal frame ratenewrate に更新するための処理が有効になるまで待つ。

      2. newrate および session を用いて nominal frame rate を適用する

      3. promise解決する。

  8. promise を返す。

XR Compositor が何らかの理由で nominal frame rate を変更する場合(たとえば "visible-blurred" イベント中)、フレームレート変更を引き起こしたイベントが終了した後は internal target framerate を使用すべきである。

updateRenderState(newState) メソッドは、次のフレームで適用されるように active render state の更新をキューに入れる。このメソッドに渡された XRRenderStateInit newState の未設定フィールドは変更されない。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionthis とする。

  2. sessionended 値が true である場合、InvalidStateError を投げ、これらの手順を中止する。

  3. newStatebaseLayersession 以外の XRSession で作成された場合、InvalidStateError を投げ、これらの手順を中止する。

  4. newStateinlineVerticalFieldOfView が設定されており、かつ sessionimmersive session である場合、InvalidStateError を投げ、これらの手順を中止する。

  5. newStatedepthNeardepthFarinlineVerticalFieldOfViewbaseLayerlayers のいずれも設定されていない場合、これらの手順を中止する。

  6. session および newState を用いて update the pending layers state を実行する。

  7. activeStatesessionactive render state とする。

  8. sessionpending render statenull である場合、 それを activeState のコピーに設定する。

  9. newStatepassthroughFullyObscured 値が設定されている場合、sessionpending render statepassthroughFullyObscurednewStatepassthroughFullyObscured に設定する。

  10. newStatedepthNear 値が設定されている場合、sessionpending render statedepthNearnewStatedepthNear に設定する。

  11. newStatedepthFar 値が設定されている場合、sessionpending render statedepthFarnewStatedepthFar に設定する。

  12. newStateinlineVerticalFieldOfView が設定されている場合、sessionpending render stateinlineVerticalFieldOfViewnewStateinlineVerticalFieldOfView に設定する。

  13. newStatebaseLayer が設定されている場合、sessionpending render statebaseLayernewStatebaseLayer に設定する。

要求されたとき、XRSession session は、次の手順を実行して pending render state を適用しなければならない:

  1. activeStatesessionactive render state とする。

  2. newStatesessionpending render state とする。

  3. sessionpending render statenull に設定する。

  4. oldBaseLayeractiveStatebaseLayer とする。

  5. oldLayersactiveStatelayers とする。

  6. 次の手順を実行するためにタスクをキューに入れる:

    1. activeStatenewState に設定する。

    2. oldBaseLayeractiveStatebaseLayer と等しくない場合、oldLayersactiveStatelayers と等しくない場合、またはいずれかのレイヤーの寸法が変化した場合、session について viewports を更新する

    3. activeStateinlineVerticalFieldOfViewsessionminimum inline field of view 未満である場合、 activeStateinlineVerticalFieldOfViewsessionminimum inline field of view に設定する。

    4. activeStateinlineVerticalFieldOfViewsessionmaximum inline field of view を超える場合、 activeStateinlineVerticalFieldOfViewsessionmaximum inline field of view に設定する。

    5. activeStatedepthNearsessionminimum near clip plane 未満である場合、activeStatedepthNearsessionminimum near clip plane に設定する。

    6. activeStatedepthFarsessionmaximum far clip plane を超える場合、activeStatedepthFarsessionmaximum far clip plane に設定する。

    7. baseLayeractiveStatebaseLayer とする。

    8. activeStatecomposition enabledoutput canvas を次のように設定する:

      sessioninline session であり、baseLayercomposition enabledfalse に設定した XRWebGLLayer のインスタンスである場合:

      activeStatecomposition enabled 真偽値を false に設定する。

      activeStateoutput canvasbaseLayercontextcanvas に設定する。

      それ以外の場合:

      activeStatecomposition enabled 真偽値を true に設定する。

      activeStateoutput canvasnull に設定する。

requestReferenceSpace(type) メソッドは、可能であれば、指定された type の新しい XRReferenceSpace を構築する。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. promise を、この XRSession関連するレルム内の 新しい Promise とする。

  2. 次の手順を in parallel で実行する:

    1. type および session について reference space is supported を実行した結果が false である場合、promiseNotSupportedError拒否する タスクをキューに入れ、これらの手順を中止する。

    2. type 型の参照空間をトラッキングするために必要なプラットフォームリソースを設定する。

      ユーザーエージェントは、そのような参照空間についてトラッキングが確立されるのを 待ってから requestReferenceSpace() を解決する必要はない。セッションが最初にトラッキングの確立を試みているとき、 getViewerPose()null を返しても問題なく、コンテンツはこの時間を使ってスプラッシュスクリーンなどを表示できる。 type"bounded-floor" であり、境界がまだ確立されていない場合、ユーザーエージェントは境界を小さな初期領域に設定し、 境界が確立されたときに reset イベントを使用してもよい。
    3. 次の手順を実行するためにタスクをキューに入れる:

    4. type および session を用いて referenceSpace という 参照空間を作成する

    5. promisereferenceSpace解決する。

  3. promise を返す。

XRSession は、 list of active XR input sourcesXRInputSourcelist)および list of active XR tracked sourcesXRInputSourcelist)を持ち、どちらも最初は空の list でなければならない。

XRSession は、 XR device を持つ。これは初期化時に設定された XR device である。

inputSources 属性は、XRSessionlist of active XR input sources を返す。

trackedSources 属性は、XRSessionlist of active XR tracked sources を返す。 list of active XR tracked sources は、 tracked-sourcesset of granted features に含まれている場合にのみ 追加されなければならない。

ユーザーエージェントは、XR device に関連付けられた任意の XR input source を監視しなければならない。これには、 XR input source が 追加、削除、または変更されたときの検出が含まれる。

XRSession は、 最初は false である promise resolved フラグを持つ。

注: このフラグの目的は、ユーザーコードが実際に イベントリスナーを登録する機会を得るまで、add input sourceremove input source、および change input source アルゴリズムが実行されないことを保証することである。実装が、セッションが解決された後に入力ソースの変更の 監視を開始することを選ぶだけであれば、このフラグは必要ない場合がある。

XRSession session で新しい XR input source利用可能になるとき、ユーザーエージェントは次の手順を 実行しなければならない:

  1. sessionpromise resolved フラグが設定されていない場合、 これらの手順を中止する。

  2. added primary sources を新しい list とする。

  3. added tracked sources を新しい list とする。

  4. 新しい各 XR input source について:

    1. inputSource を、この XRSession関連するレルム内の 新しい XRInputSource とし、次の手順を実行する:

      inputSourceprimary input source である場合:

      inputSourceadded primary sources に追加する。

      それ以外の場合で、tracked-sourcessessionset of granted features に含まれる場合:

      inputSourceadded tracked sources に追加する。

  5. 次の手順を実行するためにタスクをキューに入れる:

    1. sessionlist of active XR input sourcesadded primary sources拡張する。

    2. added primary sources が空でない場合、XRInputSourcesChangeEventsession 上で inputsourceschange という名前で発火し、addedadded primary sources に設定する。

    3. sessionlist of active XR tracked sourcesadded tracked sources拡張する。

    4. added tracked sources が空でない場合、XRInputSourcesChangeEventsession 上で trackedsourceschange という名前で発火し、addedadded tracked sources に設定する。

XRSession session で、以前に追加された任意の XR input source利用できなくなるとき、 ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionpromise resolved フラグが設定されていない場合、 これらの手順を中止する。

  2. removed primary sources を新しい list とする。

  3. removed tracked sources を新しい list とする。

  4. 利用できなくなった各 XR input source について:

    1. inputSource を、XR input source に関連付けられた sessionlist of active XR input sources 内の XRInputSource とし、次の手順を実行する:

      inputSourceprimary input source である場合:

      inputSourceremoved primary sources に追加する。

      それ以外の場合で、tracked-sourcessessionset of granted features に含まれる場合:

      inputSourceremoved tracked sources に追加する。

  5. 次の手順を実行するためにタスクをキューに入れる:

    1. removed primary sources 内の各 XRInputSource を、sessionlist of active XR input sources から 削除する。

    2. removed primary sources が空でない場合、XRInputSourcesChangeEventsession 上で inputsourceschange という名前で発火し、removedremoved primary sources に設定する。

    3. removed tracked sources 内の各 XRInputSource を、sessionlist of active XR tracked sources から 削除する。

    4. removed tracked sources が空でない場合、XRInputSourcesChangeEventsession 上で trackedsourceschange という名前で発火し、removedremoved tracked sources に設定する。

注: ユーザーエージェントは、入力ソースが位置と向きの トラッキングの両方を一時的に失ったときに、このイベントを発火してもよい。これは物理的な手持ちコントローラー入力ソースに 限って行うことが推奨される。トラッキングされた手の入力ソースでこれが発生した場合、このイベントを発火することは 推奨されない。これは頻繁に発生するためである。また、トラッカーオブジェクト入力ソースでこれが発生した場合も、 アプリケーションが同一性の概念を維持することが難しくなるため推奨されない。

handednesstargetRayModeprofilesgripSpace の存在、または任意の XR input source について primary input source または tracked input source としての状態が、 XRSession session変化するとき、ユーザーエージェントは 次の手順を実行しなければならない:

  1. sessionpromise resolved フラグが設定されていない場合、 これらの手順を中止する。

  2. added primary sources を新しい list とする。

  3. removed primary sources を新しい list とする。

  4. added tracked sources を新しい list とする。

  5. removed tracked sources を新しい list とする。

  6. 変更された各 XR input source について:

    1. oldInputSource を、以前に XR input source に関連付けられていた sessionlist of active XR input sources 内の XRInputSource とし、次の手順を実行する:

      oldInputSourceprimary input source である場合、またはその状態が primary input source から tracked input source に変化した場合:

      oldInputSourceremoved primary sources に追加する。

      それ以外の場合で、tracked-sourcessessionset of granted features に含まれる場合:

      oldInputSourceremoved tracked sources に追加する。

    2. newInputSource を、session関連するレルム内の 新しい XRInputSource とし、次の手順を実行する:

      newInputSourceprimary input source である場合、またはその状態が tracked input source から primary input source に変化した場合:

      newInputSourceadded primary sources に追加する。

      それ以外の場合で、tracked-sourcessessionset of granted features に含まれる場合:

      newInputSourceadded tracked sources に追加する。

  7. 次の手順を実行するためにタスクをキューに入れる:

    1. removed primary sources 内の各 XRInputSource を、sessionlist of active XR input sources から 削除する。

    2. sessionlist of active XR input sourcesadded primary sources拡張する。

    3. added primary sources または removed primary sources が空でない場合、 XRInputSourcesChangeEventsession 上で inputsourceschange という名前で発火し、addedadded primary sources に、removedremoved primary sources に設定する。

    4. removed tracked sources 内の各 XRInputSource を、sessionlist of active XR tracked sources から 削除する。

    5. sessionlist of active XR input sourcesadded tracked sources拡張する。

    6. added tracked sources または removed tracked sources が空でない場合、 XRInputSourcesChangeEventsession 上で trackedsourceschange という名前で発火し、addedadded tracked sources に、removedremoved tracked sources に設定する。

XRSession は enum である visibility state 値を持つ。 inline sessions について、 visibility state は、DocumentvisibilityState を反映しなければならない。 immersive sessions について、 visibility state は、セッションの状態に最もよく一致する次の値の いずれかに設定されなければならない。

visibilityState 属性は、XRSessionvisibility state を返す。 onvisibilitychange 属性は、visibilitychange イベント型に対する イベントハンドラー IDL 属性である。

visibility state は、XR animation frame の処理中を除き、ユーザーエージェントによっていつでも 変更されてもよい。またユーザーエージェントは、可能な場合、XR プラットフォームを監視して、ユーザーエージェントの外部で セッションの可視性が影響を受けた時点を観察し、それに応じて visibility state を更新すべきである。

注: XRSessionvisibility state は、HTML 文書の可視性を必ずしも意味しない。 システム構成によっては、immersive session が アクティブな間もページが表示され続ける場合がある。(たとえば、PC に接続されたヘッドセットが immersive session からのコンテンツを表示している間も、 モニター上にページが表示され続ける場合がある。)開発者はページの可視性を判断するために、引き続き Page Visibility に依存すべきである。

注: XRSessionvisibility state は、immersive session がアクティブな間も 2D コンテンツが表示され続けるテザー接続セッションにおいて、マウスの挙動に影響したり制限したりしない。 コンテンツがマウスの挙動をより強く制御したい場合は、[pointerlock] API の使用を検討すべきである。

XRSystem では、 フレームレートを説明できるいくつかの定義がある:

XRSession は、 target frame rate である internal target frameRate を持ってもよい。

XRSession は、 nominal frame rate である internal nominal frameRate を持ってもよい。 effective frame ratenominal frame rate より低い場合、XR Compositor はリプロジェクションまたはその他の 技法を使用して体験を改善してもよい。これは任意であり、inline sessions には存在してはならない。

frameRate 属性は、internal nominal framerate を反映する。XRSessioninternal nominal framerate を持たない場合、 null を返す。

onframeratechange 属性は、frameratechange イベント型に対する イベントハンドラー IDL 属性である。 XRSessionnominal frame rate が何らかの理由で変更された場合、新しい nominal frame rate と XRSession を用いて nominal frame rate を適用しなければならない。

supportedFrameRates 属性は、サポートされる target frame rate 値のリストを返す。この属性は任意であり、inline sessions、または作者にフレームレートの制御を 許可しない XRSystem には 存在してはならない。XRSessionsupportedFrameRates 属性をサポートする場合、frameRate もサポートしなければならない。

XRSession は、 viewer reference space を持つ。これは、identity transformorigin offset を持つ、型 "viewer"XRReferenceSpace である。

XRSession は、 list of views を持つ。これは、XR device が 提供するビューに対応する viewlist である。 list of viewsXRSession 中は 不変であり、最初は active でない可能性のある secondary views を含め、セッション中に表面化される可能性のある 任意の views を含まなければならない。

list of views 内の primary views は、 XRSessionmode および set of granted features によって決定されなければならない:

onend 属性は、end イベント型に対する イベントハンドラー IDL 属性である。

oninputsourceschange 属性は、inputsourceschange イベント型に対する イベントハンドラー IDL 属性である。

onselectstart 属性は、selectstart イベント型に対する イベントハンドラー IDL 属性である。

onselectend 属性は、selectend イベント型に対する イベントハンドラー IDL 属性である。

onselect 属性は、select イベント型に対する イベントハンドラー IDL 属性である。

onsqueezestart 属性は、squeezestart イベント型に対する イベントハンドラー IDL 属性である。

onsqueezeend 属性は、squeezeend イベント型に対する イベントハンドラー IDL 属性である。

onsqueeze 属性は、squeeze イベント型に対する イベントハンドラー IDL 属性である。

4.2. XRRenderState

XRRenderState は、XRSession の 出力がどのように合成されるかに影響する、構成可能な値の集合を表す。ある XRSessionactive render state はフレーム境界間でのみ変更でき、 更新は updateRenderState() によってキューに入れられる。

dictionary XRRenderStateInit {
  double depthNear;
  double depthFar;
  boolean passthroughFullyObscured;
  double inlineVerticalFieldOfView;
  XRWebGLLayer? baseLayer;
  sequence<XRLayer>? layers;
};

[SecureContext, Exposed=Window] interface XRRenderState {
  readonly attribute double depthNear;
  readonly attribute double depthFar;
  readonly attribute boolean? passthroughFullyObscured;
  readonly attribute double? inlineVerticalFieldOfView;
  readonly attribute XRWebGLLayer? baseLayer;
};

XRRenderStateoutput canvas を持つ。これは最初 null に設定される HTMLCanvasElement である。output canvas は、inline session のためにレンダリングされたコンテンツを表示する DOM 要素である。

XRRenderState はさらに、最初は true である composition enabled 真偽値を持つ。レンダリングコマンドが API によって提供されるサーフェスに対して実行され、XR Compositor によって表示される場合、XRRenderStatecomposition enabled を持つとみなされる。 inline session のための レンダリングが output canvas に直接表示されるように行われる場合、XRRenderStatecomposition enabled フラグは false でなければならない。

注: この時点で、XRRenderStateoutput canvas を持つのは、composition enabledfalse に設定されている場合のみである。しかし仕様の将来バージョンでは、 ミラーリングやレイヤー合成のような、合成を必要とするより高度な用途をサポートする output canvases を設定する方法が導入される可能性が高い。

XRRenderState オブジェクトが XRSession session のために作成されるとき、ユーザーエージェントは次の手順を実行して レンダーステートを初期化しなければならない:

  1. state を、session関連するレルム内の 新しい XRRenderState オブジェクトとする。

  2. statedepthNear0.1 に初期化する。

  3. statedepthFar1000.0 に初期化する。

  4. statepassthroughFullyObscuredfalse に初期化する。

  5. stateinlineVerticalFieldOfView を次のように初期化する:

    sessioninline session である場合:

    stateinlineVerticalFieldOfViewPI * 0.5 に初期化する。

    それ以外の場合:

    stateinlineVerticalFieldOfViewnull に初期化する。

  6. statebaseLayernull に初期化する。

depthNear 属性は、viewer から近クリップ平面までの距離をメートル単位で定義する。depthFar 属性は、viewer から遠クリップ平面までの距離をメートル単位で定義する。

depthNeardepthFar は、XRViewprojectionMatrix の計算に使用される。レンダリング中に projectionMatrix が使用される場合、viewer までの距離が depthNeardepthFar の間にあるジオメトリのみが描画される。これらはまた、XRWebGLLayer の深度バッファの値がどのように解釈されるかも決定する。depthNeardepthFar より大きくてもよい。

注: 通常、レンダリング用の透視投影行列を構築する際、 開発者は視錐台と近および遠クリップ平面を指定する。immersive XR device に表示する場合、正しい視錐台は、使用される光学系、 ディスプレイ、およびカメラの何らかの組み合わせによって決定される。ただし、近および遠クリップ平面は、 適切な値がレンダリングされるコンテンツの種類に依存するため、アプリケーションによって変更されてもよい。

passthroughFullyObscured 属性は、 作者がビューポートを仮想コンテンツで完全に覆う意図があることを示す、作者から XRSystem への ヒントである。作者は、ビューポートが不透明ピクセルで覆われなくなったら、このフラグを false に 戻すべきである。

注: XRSystem は、 これをパススルーを一時的に無効化するヒントとして使用してもよい。シースルー光学系を備えたデバイスでは、 ユーザーは引き続き環境を見ることになり、このフラグは効果を持たない。

inlineVerticalFieldOfView 属性は、 "inline" XRSession の 投影行列を計算するときに使用される、デフォルトの垂直視野角をラジアン単位で定義する。投影行列の計算では output canvas の アスペクト比も考慮される。inline sessionsinline-stereo が有効な場合、ユーザーエージェントは output canvas のジオメトリを用いてビューごとの投影行列を 計算しなければならない。この値は immersive sessions では null でなければならない。

baseLayer 属性は、XR compositor が 画像を取得する XRWebGLLayer を定義する。

4.3. アニメーションフレーム

XRSessionXR device のトラッキング状態に関する情報を提供する主な方法は、 XRSession インスタンス上で requestAnimationFrame() を呼び出すことによってスケジュールされるコールバックを介することである。

callback XRFrameRequestCallback = undefined (DOMHighResTimeStamp time, XRFrame frame);

XRFrameRequestCallback オブジェクトは、最初は false に設定される cancelled 真偽値を持つ。

XRSession は、 最初は空である list of animation frame callbacks、同じく最初は空である list of currently running animation frame callbacks、および最初は 0 である数値の animation frame callback identifier を持つ。

requestAnimationFrame(callback) メソッドは、ユーザーエージェントが次にデバイスのアニメーションフレームを実行したいときに実行されるよう、 callback をキューに入れる。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionthis とする。

  2. sessionended 値が true である場合、0 を返し、 これらの手順を中止する。

  3. sessionanimation frame callback identifier を 1 増やす。

  4. callback を、sessionanimation frame callback identifier の 現在値に関連付けて、sessionlist of animation frame callbacks に追加する。

  5. sessionanimation frame callback identifier の 現在値を返す。

cancelAnimationFrame(handle) メソッドは、与えられた animation frame callback identifier handle によって既存のアニメーションフレームコールバックを取り消す。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. sessionthis とする。

  2. sessionlist of animation frame callbacks または sessionlist of currently running animation frame callbacks の中から、handle の値に関連付けられたエントリーを見つける。

  3. そのようなエントリーがある場合、その cancelled 真偽値を true に設定し、 それを sessionlist of animation frame callbacks から削除する。

renderState state を用いて layers state を確認するには、ユーザーエージェントは次の手順を実行しなければならない:
  1. statebaseLayernull である場合、false を返す。

  2. true を返す。

注: WebXR layers module は、このアルゴリズムに 新しい意味論を導入する。

XRSession session についてフレームが レンダリングされるべきかを判断するには、ユーザーエージェントは次の手順を実行しなければならない:
  1. sessionrenderStatecheck the layers state を実行した結果が false の場合、 false を返す。

  2. sessioninline session であり、sessionrenderStateoutput canvasnull である場合、 false を返す。

  3. true を返す。

XRSession session が、XR device から タイムスタンプ frameTime に対する更新済みの viewer 状態を受け取ると、XR animation frame を実行する。これは list of animation frame callbacks が空であるかどうかにかかわらず、 次の手順を実行しなければならない:

  1. 次の手順を実行するためにタスクをキューに入れる:

    1. nowcurrent high resolution time とする。

    2. framesessionanimation frame とする。

    3. frametimeframeTime に設定する。

    4. framepredictedDisplayTimeframeTime に設定する。

    5. sessionimmersive session である場合、framepredictedDisplayTime を、XR Compositor がこの XR animation frame を表示すると予想される平均タイムスタンプに設定する。

    6. list of views 内の各 view について、 viewviewport modifiable フラグを true に設定する。

    7. list of views 内の任意の viewactive フラグが、前回の XR animation frame 以降に変化している場合、viewports を更新する

    8. フレームが session について レンダリングされるべき場合:

      1. sessionlist of currently running animation frame callbacks を、sessionlist of animation frame callbacks に設定する。

      2. sessionlist of animation frame callbacks を空リストに設定する。

      3. frameactive 真偽値を true に設定する。

      4. frame について frame updates を適用する

      5. sessionlist of currently running animation frame callbacks 内の各 entry について、順に:

      6. entrycancelled 真偽値が true である場合、次のエントリーに進む。

      7. entry を « now, frame » および "report" で 呼び出す

      8. sessionlist of currently running animation frame callbacks を空の list に設定する。

      9. frameactive 真偽値を false に設定する。

    9. sessionpending render statenull でない場合、pending render state を適用する

Window インターフェイスの requestAnimationFrame() メソッドの挙動は、アクティブな XRSession が 存在しても変更されない。また、任意の XRSession 上で requestAnimationFrame() を呼び出しても、WindowrequestAnimationFrame() といかなる形でも相互作用しない。active immersive session は、ページを遮蔽する場合、 browsing contextrendering opportunity に影響してもよい。active immersive session 中に 2D ブラウザー表示が可視である場合 (すなわち、セッションがテザー接続ヘッドセット上で実行されている場合)、WindowrequestAnimationFrame() および requestIdleCallback() によって実行されるコールバックのタイミングは、セッションの requestAnimationFrame() のタイミングと一致しない場合があり、XR コンテンツのレンダリングにおいてユーザーが依存すべきではない。

注: ユーザーエージェントは、XRSessionrequestAnimationFrame()WindowrequestAnimationFrame() によってスケジュールされたコールバック中に呼び出された場合、開発者コンソールに警告を表示したいと考えるかもしれない。 これは、active immersive sessionbrowsing contextrendering opportunity に影響する場合、それらのコールバックが発生する保証がなく、 実行されたとしても正しいタイミングを持たない可能性があるためである。

immersive sessionrendering opportunities を妨げる場合、Window requestAnimationFrame() に渡されたコールバックは、セッションがアクティブな間に処理されない場合がある。これは使用されるデバイスの種類に依存し、 没入コンテンツが HTML 文書を完全に遮蔽するモバイルまたはスタンドアロンデバイスで発生する可能性が最も高い。 そのため、開発者は、同じレンダリングロジックを共有している場合であっても、Window requestAnimationFrame() コールバックを使って XRSession requestAnimationFrame() コールバックをスケジュールしたり、その逆を行ったりすることに依存してはならない。この指針に従わないアプリケーションは、 すべてのプラットフォームで適切に実行されない可能性がある。これら 2 種類のアニメーションループ間を遷移したい アプリケーションにとって、より効果的なパターンを以下に示す:
let xrSession = null;

function onWindowAnimationFrame(time) {
  window.requestAnimationFrame(onWindowAnimationFrame);

  // This may be called while an immersive session is running on some devices,
  // such as a desktop with a tethered headset. To prevent two loops from
  // rendering in parallel, skip drawing in this one until the session ends.
  if (!xrSession) {
    renderFrame(time, null);
  }
}

// The window animation loop can be started immediately upon the page loading.
window.requestAnimationFrame(onWindowAnimationFrame);

function onXRAnimationFrame(time, xrFrame) {
  xrSession.requestAnimationFrame(onXRAnimationFrame);
  renderFrame(xrFrame.predictedDisplayTime, xrFrame);
}

function renderFrame(time, xrFrame) {
  // Shared rendering logic.
}

// Assumed to be called by a user gesture event elsewhere in code.
async function startXRSession() {
  xrSession = await navigator.xr.requestSession('immersive-vr');
  xrSession.addEventListener('end', onXRSessionEnded);
  // Do necessary session setup here.
  // Begin the session's animation loop.
  xrSession.requestAnimationFrame(onXRAnimationFrame);
}

function onXRSessionEnded() {
  xrSession = null;
}

HTML 文書へのレンダリングに inline sessions を使用するアプリケーションは、アニメーションループを調整するために 特別な手順を取る必要はない。なぜなら、immersive session がアクティブな間、 ユーザーエージェントが任意の inline sessions のアニメーションループを自動的に一時停止するためである。

4.4. XR Compositor

ユーザーエージェントは、XR device への提示とフレームタイミングを扱う XR Compositor を維持しなければならない。コンポジターは、状態が文書によって作成された どのグラフィックスコンテキストの状態からも分離された、独立したレンダリングコンテキストを使用しなければならない。 コンポジターは、ページがコンポジターの状態を破損したり、他のページまたはアプリケーションからコンテンツを 読み戻したりすることを防がなければならない。コンポジターはまた、ページの性能を、適切なフレームレートで 新しい画像をユーザーに提示する能力から切り離すために、別のスレッドまたはプロセスで実行されなければならない。 コンポジターは、デバイスメニューのような追加のデバイスまたはユーザーエージェント UI を、レンダリングされた コンテンツの上に合成してもよい。

注: この仕様の将来の拡張は、同じページから来る 複数のレイヤーを合成するためにもコンポジターを利用する可能性がある。

5. フレーム ループ

5.1. XRFrame

XRFrame は、 XRSession に対する すべてのトラッキング対象オブジェクトの状態のスナップショットを表す。アプリケーションは、XRFrameRequestCallback を指定して XRSession 上で requestAnimationFrame() を呼び出すことによって、XRFrame を取得できる。 コールバックが呼び出されると、XRFrame が渡される。 select イベントのようにトラッキング状態を伝達する必要があるイベントも、XRFrame を提供する。

[SecureContext, Exposed=Window] interface XRFrame {
  [SameObject] readonly attribute XRSession session;
  readonly attribute DOMHighResTimeStamp predictedDisplayTime;

  XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace);
  XRPose? getPose(XRSpace space, XRSpace baseSpace);
};

XRFrame は、 最初は false に設定される active 真偽値と、最初は false に設定される animationFrame 真偽値を持つ。

session 属性は、その XRFrame を生成した XRSession を返す。

immersive session の場合、predictedDisplayTime 属性は、この XRFrame が デバイスのディスプレイ上に表示されると予想される平均時点に対応する DOMHighResTimeStamp を返さなければならない。inline session の場合、predictedDisplayTimeXRFrameRequestCallback に渡されたタイムスタンプと同じ値を返さなければならない。

predictedDisplayTime は、requestAnimationFrame() コールバックがスケジュールされた時点や実行された時点ではなく、フレームが表示される時点であるべき状態で、 アニメーションする XR シーンをレンダリングできるようにすることを意図している。

predictedDisplayTime は、アプリケーションがレンダリングに使える時間を推定するために使用されることを意図していない。なぜなら、 XR Compositor は通常、 フレームが送信された後に追加の処理を行う必要があるためである。体験が predictedDisplayTime まで処理できると仮定すると、XR Compositor は 送信されたフレームを利用できず、アプリケーションは目標フレームレートを達成できない。

XRFrame は、 与えられた time におけるすべてのトラッキング対象オブジェクトの状態を表し、 その time におけるこの状態に関する具体的な情報を格納するか、問い合わせることができる。

getViewerPose(referenceSpace) メソッドは、 viewer のポーズを referenceSpace に相対する XRViewerPose として、XRFrametime において提供する。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. framethis とする。

  2. sessionframesession オブジェクトとする。

  3. frameanimationFrame 真偽値が false である場合、 InvalidStateError を投げ、これらの手順を中止する。

  4. pose を、session関連するレルム内の 新しい XRViewerPose オブジェクトとする。

  5. sessionviewer reference spacereferenceSpace 内での、frame によって表される時刻における pose を埋める処理を、 force emulationtrue に設定して pose に対して行う。

  6. posenull である場合、null を返す。

  7. xrviews を空の list とする。

  8. offset0 とする。

  9. session 上の list of views 内の各 activeview view について、次の手順を実行する:

    1. xrview を、session関連するレルム内の新しい XRView オブジェクトとする。

    2. xrviewunderlying viewview に初期化する。

    3. xrvieweyevieweye に初期化する。

    4. xrviewindexoffset に初期化する。

    5. xrviewframeframe に初期化する。

    6. xrviewsessionsession に初期化する。

    7. xrviewreference spacereferenceSpace に初期化する。

    8. viewtransform を、session関連するレルム内で、 viewview offset に等しい 新しい XRRigidTransform オブジェクトとする。

    9. xrviewtransform プロパティを、XRViewerPosetransform に、session の関連するレルム内の viewtransform 変換を 乗算した結果に設定する。

    10. xrviewxrviews追加する。

    11. offset1 増やす。

  10. poseviewsxrviews に設定する

  11. pose を返す。

getPose(space, baseSpace) メソッドは、 spacebaseSpace に相対するポーズを、XRPose として、 XRFrame によって 表される時刻において提供する。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. framethis とする。

  2. pose を、frame関連するレルム内の 新しい XRPose オブジェクトとする。

  3. frame によって表される時刻における baseSpace 内の spacepose を埋める処理を pose に対して行う。

  4. pose を返す。

frame update は、 XRFrame が 与えられたときに実行できるアルゴリズムであり、各 XRFrame で 実行されることを意図している。

すべての XRSessionlist of frame updates を持つ。これは frame updateslist であり、最初は空の list である。

XRFrame frame について frame updates を適用するには、ユーザーエージェントは次の手順を 実行しなければならない:

  1. framesessionlist of frame updates 内の各 frame update について、次の手順を実行する:

    1. frame updateframe で実行する。

注: この仕様は frame updates を定義しないが、 他の仕様がいくつか追加する可能性がある。

6. 空間

WebXR Device API の中核機能は、空間トラッキングを提供する能力である。空間は、アプリケーションが、 トラッキング対象エンティティがユーザーの物理環境および互いに対して空間的にどのように関係するかを 推論できるようにするインターフェイスである。

6.1. XRSpace

XRSpace は、 物理的位置に対応する原点を持つ仮想座標系を表す。API から要求される、または API に与えられる空間データは常に、 特定の XRSpace に関連して、 特定の XRFrame の時点で表現される。 ポーズ位置などの数値は、その空間内でその原点に相対する座標である。このインターフェイスは意図的に不透明である。

[SecureContext, Exposed=Window] interface XRSpace : EventTarget {

};

XRSpace は、 その XRSpace を作成した XRSession に設定される session を持つ。

XRSpace は、 空間内の位置と向きである native origin を持つ。XRSpacenative origin は、 XR device の基盤となるトラッキングシステムによって更新されることがあり、 異なる XRSpace は、それぞれの native origins がどのようにトラッキングされ更新されるかについて、 異なる意味論を定義する場合がある。

XRSpaceeffective origin を持つ。これは XRSpacecoordinate system の基礎である。

effective space から native origin の空間への変換は、origin offset によって定義される。これは最初に identity transform に設定される XRRigidTransform である。言い換えると、effective origin は、 origin offsetnative origin乗算することで得られる。

XRSpaceeffective origin は、別の XRSpace の座標系内で、 XRPose としてのみ 観察できる。これは XRFramegetPose() メソッドによって返される。XRSpace 間の 空間的関係は、XRFrame 間で 変化してもよい。

XRSpace space の、XRSpace baseSpace 内における、XRFrame frame によって表される時刻での pose を埋める処理を、 XRPose pose に対して、任意の force emulation フラグを用いて行うには、 ユーザーエージェントは次の手順を実行しなければならない:

  1. frameactive 真偽値が false である場合、InvalidStateError を投げ、これらの手順を中止する。

  2. sessionframesession オブジェクトとする。

  3. spacesessionsession と等しくない場合、InvalidStateError を投げ、これらの手順を中止する。

  4. baseSpacesessionsession と等しくない場合、InvalidStateError を投げ、これらの手順を中止する。

  5. poses may be reported かどうかを確認し、そうでない場合は SecurityError を投げ、これらの手順を中止する。

  6. sessionvisibilityState"visible-blurred" であり、space または baseSpaceXRInputSource に関連付けられている場合、posenull に設定し、これらの手順を中止する。

  7. limit を、spacebaseSpace の間で poses must be limited かどうかの結果とする。

  8. transformposetransform とする。

  9. frametime における baseSpace に相対する space のポーズを、XR device の トラッキングシステムに問い合わせ、次の手順を実行する:

    limitfalse であり、トラッキングシステムが、baseSpace に 相対する space のポーズについて、位置が能動的にトラッキングされている、または静的に既知である 6DoF ポーズを提供する場合:

    transformorientation を、baseSpacecoordinate system 内における spaceeffective origin の向きに設定する。

    transformposition を、baseSpacecoordinate system 内における spaceeffective origin の位置に設定する。

    サポートされる場合、poselinearVelocity を、baseSpacecoordinate system と比較した spaceeffective origin の線速度に設定する。

    サポートされる場合、poseangularVelocity を、baseSpacecoordinate system と比較した spaceeffective origin の角速度に設定する。

    poseemulatedPositionfalse に設定する。

    それ以外の場合で、limitfalse であり、トラッキングシステムが 3DoF ポーズ、または baseSpace に相対する space のポーズについて位置が能動的にトラッキングされておらず、 静的にも既知でない 6DoF ポーズを提供する場合:

    transformorientation を、baseSpacecoordinate system 内における spaceeffective origin の向きに設定する。

    transformposition を、baseSpacecoordinate system 内における spaceeffective origin の位置についての トラッキングシステムの最良推定値に設定する。これには首モデルや腕モデルなどの計算済みオフセットが 含まれてもよい。位置推定が利用できない場合、最後に既知だった位置を使用しなければならない。

    poselinearVelocitynull に設定する。

    poseangularVelocitynull に設定する。

    poseemulatedPositiontrue に設定する。

    それ以外の場合で、baseSpace に相対する space のポーズが過去に決定されており、 force emulationtrue である場合:

    transformposition を、baseSpacecoordinate system 内における spaceeffective origin の最後に既知だった位置に設定する。

    transformorientation を、baseSpacecoordinate system 内における spaceeffective origin の最後に既知だった向きに設定する。

    poselinearVelocitynull に設定する。

    poseangularVelocitynull に設定する。

    poseemulatedPosition 真偽値を true に設定する。

    それ以外の場合:

    posenull に設定する。

注: XRPoseemulatedPosition 真偽値は、baseSpace の位置がエミュレートされているかどうかを示すものではなく、 baseSpace に相対する space の位置を評価する際にエミュレーションに依存するかどうかのみを 示す。たとえば、3DoF トラッキングを備えた コントローラーは、その targetRaySpace または gripSpaceXRReferenceSpace に対して問い合わせられると、emulatedPositiontrue のポーズを報告する。しかし、targetRaySpace のポーズが gripSpace 内で問い合わせられた場合、それら 2 つの空間の関係は正確に既知であるべきであるため、 emulatedPositionfalse であると報告する。

6.2. XRReferenceSpace

XRReferenceSpace は、アプリケーションがユーザーの物理環境との空間的関係を確立するために使用できる、いくつかの共通の XRSpace の 1 つである。

XRReferenceSpace は、 一般に XRSession の 継続時間中は静的なままであることが期待される。最も一般的な例外は、セッション中にユーザーによって再構成される場合である。 すべての XRReferenceSpacenative origin は、+X が "Right"、+Y が "Up"、-Z が "Forward" とみなされる座標系を記述する。

enum XRReferenceSpaceType {
  "viewer",
  "local",
  "local-floor",
  "bounded-floor",
  "unbounded"
};

[SecureContext, Exposed=Window]
interface XRReferenceSpace : XRSpace {
  [NewObject] XRReferenceSpace getOffsetReferenceSpace(XRRigidTransform originOffset);

  attribute EventHandler onreset;
};

XRReferenceSpacetype を持ち、これは XRReferenceSpaceType である。

XRReferenceSpace は、最も頻繁には requestReferenceSpace() を呼び出すことで取得される。この呼び出しに渡された XRReferenceSpaceType enum 値が サポートされる場合、XRReferenceSpace (またはそれを拡張するインターフェイス)のインスタンスが作成される。型は、参照空間が示すトラッキング挙動を 示す:

注: 参照空間の Y 軸に関する基盤となるプラットフォームの規約は、 異なる種類の XRReferenceSpace 間で一貫していると仮定される。言い換えると、XR システムが複数の参照空間をサポートする場合、それらの Y 軸は、 それらが作成された XRSession の 継続時間中、互いに平行で同じ方向を指す。これは "viewer" には適用されない。これは、その向きについて基盤となるプラットフォームの規約に依存しないためである。"unbounded" 参照空間は、原点が近い場合には Y 軸を他の参照空間と揃えるべきであるが、ユーザーが長距離移動した場合には 逸脱してもよい。

"local" 参照空間をサポートするデバイスは、必要に応じてエミュレーションを通じて "local-floor" 参照空間をサポートしなければならず、その逆も同様である。

onreset 属性は、reset イベント型に対する イベントハンドラー IDL 属性である。

XRSession session のために XRReferenceSpaceType typeXRReferenceSpace が要求されたとき、ユーザーエージェントは次の手順を実行して 参照空間を作成しなければならない:

  1. referenceSpace を次のように初期化する:

    typebounded-floor である場合:

    referenceSpace を、session関連するレルム内の 新しい XRBoundedReferenceSpace とする。

    それ以外の場合:

    referenceSpace を、session関連するレルム内の 新しい XRReferenceSpace とする。

  2. referenceSpacetypetype に初期化する。

  3. referenceSpacesessionsession に初期化する。

  4. referenceSpace を返す。

与えられた参照空間型 typeXRSession session について、reference space がサポートされるか確認するには、次の手順を実行する:
  1. typesessionset of granted features含まれていない場合、 false を返す。

  2. typeviewer である場合、true を返す。

  3. typelocal または local-floor であり、sessionimmersive session である場合、true を返す。

  4. typelocal または local-floor であり、XR device が向きデータの報告をサポートする場合、 true を返す。

  5. typebounded-floor であり、sessionimmersive session である場合、XR device によって bounded reference spaces がサポートされるかどうかの 結果を返す。

  6. typeunbounded であり、sessionimmersive session であり、XR device がユーザー付近で 無制限の距離にわたる安定したトラッキングをサポートする場合、true を返す。

  7. false を返す。

getOffsetReferenceSpace(originOffset) メソッドは、呼び出されたとき次の手順を実行しなければならない:
  1. base を、このメソッドが呼び出された XRReferenceSpace とする。

  2. offsetSpace を次のように初期化する:

    baseXRBoundedReferenceSpace のインスタンスである場合:

    offsetSpace を、base関連するレルム内の 新しい XRBoundedReferenceSpace とし、offsetSpaceboundsGeometry を、各点に originOffsetinverse を乗算した baseboundsGeometry に設定する。

    それ以外の場合:

    offsetSpace を、base関連するレルム内の 新しい XRReferenceSpace とする。

  3. offsetSpacetypebasetype に設定する。

  4. offsetSpaceorigin offset を、baseorigin offsetoriginOffsetbase関連するレルム内で 乗算した結果に設定する。

  5. offsetSpace を返す。

注: 一部のアプリケーションは、マウス、キーボード、タッチ、 またはゲームパッド入力に基づくシーンナビゲーション制御を実装するために getOffsetReferenceSpace() を使用すると想定される。これにより、getOffsetReferenceSpace() は頻繁に、少なくとも入力がアクティブな期間中はフレームごとに 1 回呼び出されることになる。その結果、 UA は getOffsetReferenceSpace() による新しい XRReferenceSpace の 作成を軽量な操作にすることを強く推奨される。

6.3. XRBoundedReferenceSpace

XRBoundedReferenceSpaceXRReferenceSpace を拡張して boundsGeometry を含め、ユーザー空間の事前構成された境界を示す。

[SecureContext, Exposed=Window]
interface XRBoundedReferenceSpace : XRReferenceSpace {
  readonly attribute FrozenArray<DOMPointReadOnly> boundsGeometry;
};

XRBoundedReferenceSpace の原点は床に配置されなければならず、床面で Y 軸が 0 に等しくなるようにする。 X および Z の位置と向きは、基盤となるプラットフォームの規約に基づいて 初期化され、通常は部屋の中心付近で、論理的な前方方向を向いていることが期待される。

注: 他の XR プラットフォームでは、bounded-floor 参照空間によって提供される種類のトラッキングを、"room scale" トラッキングと呼ぶことがある。XRBoundedReferenceSpace は、複数の部屋にまたがる空間、床面の高さが不均一な領域、または非常に広い開放領域を記述することを 意図していない。そのようなシナリオを扱う必要があるコンテンツは、unbounded 参照空間を使用すべきである。

XRBoundedReferenceSpace は、XRBoundedReferenceSpace の周囲の境界を記述する native bounds geometry を持ち、 ユーザーはその内部を安全に移動できると期待できる。多角形の境界は、DOMPointReadOnly の配列として与えられ、安全な空間の端にある点のループを表す。これらの点は、native origin からのオフセットをメートル単位で記述する。点は、上から見て Y 軸の負方向の端へ向かって見るとき、 時計回りの順序で与えられなければならない。各点の y 値は 0 でなければならず、各点の w 値は 1 でなければならない。境界は床から始まり、無限に高く延びるものとみなすことができる。 それが記述する形状は凸であっても凹であってもよい。

native bounds geometry 内の各点は、 参照空間の native origin から妥当な距離に 制限されなければならない。

注: native bounds geometry の点は、すべての方向で native origin から 15 メートルに 制限することが提案される。

native bounds geometry 内の各点は、 フィンガープリンティングを防ぐのに十分なだけ 量子化されなければならない。 ユーザーの安全のため、量子化された点の値は、プラットフォームによって報告された境界の外側に出てはならない。

注: native bounds geometry の点は、 最も近い 5cm に 量子化することが提案される。

boundsGeometry 属性は DOMPointReadOnly の配列であり、各エントリーは XRBoundedReferenceSpacenative bounds geometry 内の対応するエントリーに origin offsetinverse を前乗算したものと等しい。言い換えると、これは effective origin に相対する XRBoundedReferenceSpace 座標内で同じ境界を提供する。

native bounds geometry が一時的に 利用できない場合、これは XR デバイスの初期化中、長時間のトラッキング喪失、または事前構成された空間間の移動など、 いくつかの理由で発生しうるが、boundsGeometry は空配列を報告しなければならない。

bounded reference spaces がサポートされるか確認するには、 次の手順を実行する:
  1. XR device が境界を報告できない場合、false を返す。

  2. XR device がユーザーの物理的な床の高さを識別できない場合、false を返す。

  3. true を返す。

注: 参照空間の要求時点で境界または床の高さが解決されて いない場合でも、XR デバイスがそれらをサポートすることが分かっていれば、bounded reference spaces が返されることがある。

注: コンテンツは、ユーザーに boundsGeometry を超えて移動することを要求すべきではない。物理的な周囲環境が許せば、ユーザーが境界を超えて移動することは 可能であり、その結果、記述された多角形の外側の位置値が生じる。これはエラー条件ではなく、ページコンテンツに よって適切に扱われるべきである。

注: コンテンツは一般に boundsGeometry の可視化を提供すべきではない。安全上重要な情報がユーザーに提供されることを保証するのは、 ユーザーエージェントの責任であるためである。

7. ビュー

7.1. XRViewGeometry

XRViewGeometry インターフェイスミックスインを含むオブジェクトは、ユーザーに画像を提示するために XR デバイスで使用される ディスプレイ、または現実世界に関する視覚情報を収集するために使用されるセンサーのいずれかを表す。 これらのオブジェクトは view geometry を含む。

view geometry は、viewer reference spacecoordinate system 内の点と、 containing objectscreen space 内の点との間を 変換するために使用される内部パラメーターと外部パラメーターの集合に対応する。

view geometry は、 containing object を持つ。これは、その view geometry が データを含む対象である物理的なハードウェアである。

view geometrycontaining object には、関連付けられた screen space があり、これはこの containing object がデータを読み取る、またはデータを レンダリングする 2D 平面として記述される。

view geometry は、関連付けられた view offset を持つ。これは viewer reference spacecoordinate system 内での containing object の位置と向きを記述する XRRigidTransform である。

注: view offset がどのようなものであり得るかに制約はなく、 ビューは異なる向きを持つことが許される。これは、目のディスプレイが角度を持って中心に置かれている ヘッドマウントデバイスで起こることがあり、CAVE レンダリングのようなより極端な場合にも現れうる。 このため、z ソートやカリングのような技法は目ごとに行う必要がある場合がある。

view geometry は、関連付けられた projection matrix を持つ。これは、基盤となる XR デバイスによって 提供される containing object にレンダリングする際に使用される投影を 記述する matrix である。projection matrix は、単純な視錐台によって投影を正確に記述することを 妨げる、せん断などの変換を含んでもよい。

注: この行列の逆行列は、screen space からピクセルを「読み取り」、containing object を原点として coordinate system へ戻す変換に適している。

[SecureContext, Exposed=Window] interface mixin XRViewGeometry {
  readonly attribute Float32Array projectionMatrix;
  [SameObject] readonly attribute XRRigidTransform transform;
};

XRViewGeometry は、関連付けられた internal projection matrix を持ち、これはその containing objectprojection matrix を格納する。これは最初 null である。

注: transform は、多くのレンダリングライブラリでカメラオブジェクトを配置するために使用できる。アプリケーションがより伝統的な view matrix を必要とする場合は、transform.inverse.matrix を呼び出すことで取得できる。

projectionMatrix 属性は、基盤となる view geometryprojection matrix である。アプリケーションは、この行列を 変更または分解せずに使用することが 強く推奨される。レンダリング時に提供された投影行列を使用しないと、 提示されるフレームが歪んだり、ひどくずれたりし、ユーザーにさまざまな程度の不快感をもたらす可能性がある。 この属性は、XRViewGeometryprojection matrix を取得することによって 計算されなければならない。

transform 属性は、そのオブジェクトの XRRigidTransform である。これは、そのオブジェクトを取得するために使用された XRReferenceSpace 内でのオブジェクトの位置と向きを表す。

与えられた XRViewGeometry view geometry について projection matrix を取得するには:

  1. view geometryinternal projection matrixnull でない場合、次の手順を実行する:

    1. internal projection matrix に対する IsDetachedBuffer 操作が false である場合、view geometryinternal projection matrix を返す。

  2. view geometryinternal projection matrix を、 view geometry関連するレルム内の 新しい matrix で、view geometryprojection matrix と等しいものに設定する。

  3. view geometryinternal projection matrix を返す。

7.2. XRView

XRView は、与えられた フレームにおける XR シーンへの単一の view を記述する。

view は、ユーザーに画像を提示するために XR デバイスで使用されるディスプレイ、またはディスプレイの一部に対応する。これらは、視野角、目のオフセット、 その他の光学特性を含め、view の物理的な出力特性に正しく揃ったコンテンツをレンダリングするために必要な すべての情報を取得するために使用される。Views は ユーザーの視野の重なり合う領域を覆うことがある。どの XR デバイスが使用する views の数やその順序についても保証されず、XRSession の 継続時間中に views の数が一定である必要もない。

view は、関連付けられた eye を持ち、 これはこのビューがどちらの目に表示されることが期待されるかを記述する XREye である。ビューが本質的に関連付けられた目を持たない場合(たとえばディスプレイが単眼である場合)、この値は "none" に設定されなければならない。

view は、XRSession の ライフサイクルを通じて変化する可能性がある active フラグを持つ。 Primary views は常に active フラグを true に設定しなければならない。

注: 多くの HMD は、コンテンツに 2 つの views、つまり左目用と右目用をレンダリングするよう要求する一方、 ほとんどの magic window デバイスは 1 つの view のみを要求するが、アプリケーションは特定のビュー構成を決して仮定すべきではない。 たとえば、magic window デバイスはステレオ出力が可能であれば 2 つのビューを要求することがあるが、 ステレオ出力モードがオフにされている場合、性能上の理由で単一ビューの要求に戻ることがある。同様に、HMD は 広い視野角や異なるピクセル密度のディスプレイを容易にするために、2 つを超えるビューを要求することがある。

view は、このセッションのこの時点で requestViewportScale() 呼び出しによって viewport scale を変更できるかどうかを示す内部 viewport modifiable フラグを持つ。これはアニメーションフレームの開始時に true に設定され、 getViewport() が呼び出されたときに false に設定される。

view は、このビューの要求された viewport scale を表す 内部 requested viewport scale 値を持つ。これは最初 1.0 に設定され、システムが動的 viewport scaling をサポートする場合は requestViewportScale() メソッドによって変更できる。

view は、システムによって内部的に使用される このビューの現在の viewport scale を表す内部 current viewport scale 値を持つ。これは最初 1.0 に設定される。これは、getViewport() 呼び出しによってビューポート変更が正常に適用されたとき、requested viewport scale と一致するよう更新される。

viewreference space を持つ。これは getViewerPose() でこの view を取得するために使用された XRReferenceSpace 空間である

注: 動的 viewport scaling は、アプリケーションが アニメーションフレームごとに変更できるスケール係数を用いて、フルサイズのビューポートの一部にレンダリングすることを 可能にする。これは、再割り当てなしでフレームごとに効率的に変更できることを意図している。正しいレンダリングのためには、 XR システムとアプリケーションがアクティブなビューポートについて合意していることが不可欠である。アプリケーションは 1 つのアニメーションフレーム内で XRView に対して requestViewportScale() を複数回呼び出せるが、要求されたスケールは、そのビューについてアプリケーションが getViewport() を呼び出すまで効果を持たない。アニメーションフレーム内で最初の getViewport 呼び出しが変更を適用し (現在のアニメーションフレームに即時に効果を持つ)、このアニメーションフレームの残りの間、そのビューの現在の スケール済みビューポートを固定し、そのスケールを将来のアニメーションフレームの新しいデフォルトとして設定する。 任意で、システムは内部の性能ヒューリスティックと目標フレームレートに基づき、recommendedViewportScale 属性を通じて推奨値を提供できる。

enum XREye {
  "none",
  "left",
  "right"
};

[SecureContext, Exposed=Window] interface XRView {
  readonly attribute XREye eye;
  readonly attribute unsigned long index;
  readonly attribute double? recommendedViewportScale;

  undefined requestViewportScale(double? scale);
};

XRView includes XRViewGeometry;

transform は、その reference space 内で与えられる。

eye 属性は、基盤となる vieweye を記述する。この属性の主な目的は、事前レンダリングされた ステレオコンテンツが、コンテンツの正しい部分を正しい目に提示できるようにすることである。

index 属性は、この XRViewgetViewerPose() によって views 配列内に返されるときのオフセットを記述する。

任意の recommendedViewportScale 属性は、 アプリケーションが動的 viewport scaling を構成するための requestViewportScale() 呼び出しに使用できる、UA が推奨する viewport scale 値を含む。システムが推奨スケールを決定するための ヒューリスティックまたは方法を実装していない場合、これは null である。null でない場合、その値は 0.0 より大きく 1.0 以下の数値でなければならず、詳細な性能または GPU 利用率データを提供しないよう、 量子化されなければならない。

注: 推奨 viewport scale は、考えられるスケール値の 短いリストから最も近い値に丸め、境界値に近いときの即時変更を避けるためにヒステリシスを用いることで 量子化することが提案される。(これは、視覚的に気を散らしたり不快にしたりしうるスケール値の急速な振動を 避けるのにも役立つ。)

XRView は、 関連付けられた session を持ち、これはそれを生成した XRSession である。

XRView は、 関連付けられた frame を持ち、これはそれを生成した XRFrame である。

XRView は、 関連付けられた underlying view を持ち、これはそれが表す基盤となる view である。

requestViewportScale(scale) メソッドは、ユーザーエージェントがこのビューポートの requested viewport scale を要求値に設定すべきであることを要求する。

このメソッドが XRView xrview 上で呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. scale が null または undefined である場合、これらの手順を中止する。

  2. scale が 0.0 以下である場合、これらの手順を中止する。

  3. scale が 1.0 より大きい場合、scale を 1.0 に設定する。

  4. viewxrviewunderlying view とする。

  5. viewrequested viewport scale 値を scale に設定する。

注: このメソッドは null または undefined の scale 値を無視するため、 アプリケーションは推奨スケールを提供しないシステム上でも安全に view.requestViewportScale(view.recommendedViewportScale) を使用できる。

list of views 内の任意の viewactive フラグが変化したとき、 XRSession session について、次の手順を実行することで viewports を 更新できる:

  1. layerrenderStatebaseLayer とする。

  2. layernull である場合、これらの手順を中止する。

  3. layerlist of viewport objects を空の list に設定する。

  4. list of views 内の各 activeview view について:

    1. viewport を、session について view に関連付けられた list of full-sized viewports から scaled viewport を取得する結果である XRViewport とする。

    2. viewportlayerlist of viewport objects追加する。

与えられた XRView view について、XRSession session のために scaled viewport を取得するには:

  1. glFullSizedViewport を、view に関連付けられた list of full-sized viewports からの WebGL viewport とする。

  2. scaleviewcurrent viewport scale とする。

  3. ユーザーエージェントは、最小 viewport scale 係数を適用するために scale をクランプすることを選んでもよい。

  4. glViewport を新しい WebGL viewport とする。

  5. glViewportwidth を、glFullSizedViewportwidthscale を掛けた値以下の整数値に設定する。

  6. glViewportwidth が 1 未満である場合、それを 1 に設定する。

  7. glViewportheight を、glFullSizedViewportheightscale を掛けた値以下の整数値に設定する。

  8. glViewportheight が 1 未満である場合、それを 1 に設定する。

  9. glViewportx コンポーネントを、glFullSizedViewportx コンポーネント(含む)から、glFullSizedViewportx コンポーネントに glFullSizedViewportwidth を足し、glViewportwidth を引いた値(含む) までの整数値に設定する。

  10. glViewporty コンポーネントを、glFullSizedViewporty コンポーネント(含む)から、glFullSizedViewporty コンポーネントに glFullSizedViewportheight を足し、glViewportheight を引いた値(含む) までの整数値に設定する。

  11. viewport を、session関連するレルム内の 新しい XRViewport とする。

  12. viewportxglViewportx コンポーネントに初期化する。

  13. viewportyglViewporty コンポーネントに初期化する。

  14. viewportwidthglViewportwidth に初期化する。

  15. viewportheightglViewportheight に初期化する。

  16. viewport を返す。

注: 具体的な整数値の計算は、意図的に UA の裁量に 委ねられている。width/height を切り捨て、x および y オフセットをそのまま 使用する単純な方法は有効であるが、UA は効率のためにビューポートを 2 の累乗ピクセルグリッドに揃えるなど、 指定された制約内でわずかに調整された値を選ぶこともできる。スケール済みビューポートはフルサイズの ビューポート内に完全に含まれなければならないが、UA の裁量でフルサイズのビューポート内の任意の位置に 配置されてもよい。サイズと位置の計算は決定論的でなければならず、セッション内で同一の入力値に対して 一貫した結果を返さなければならない。

7.3. プライマリビューとセカンダリビュー

view は、それにレンダリングすることが XR 体験に 必要である場合、primary view である。Primary views は、XRSession の 全継続時間にわたって active でなければならない。

view は、コンテンツがそれにレンダリングしないことを 選んでもなお動作する没入体験を生成できる場合、secondary view である。コンテンツがこれらのビューに レンダリングしないことを選んだ場合、ユーザーエージェントは再投影によってそれらを再構築できる場合がある。 Secondary views は、"secondary-views" 機能が有効でない限り active であってはならない。

primary views の例には、 ハンドヘルド AR セッションの主たるモノビュー、頭部装着型 AR/VR セッションの主たる 2 つのステレオビュー、 または inline-stereo が有効な inline sessions、 あるいは CAVE セッションのすべての壁面ビューが含まれる。

secondary views の例には、ビデオキャプチャに使用される first-person observer view、または各目に解像度と 視野角が異なる 2 つのビューがある "quad views" が含まれる。

コンテンツは任意の数のビューがあり得ると仮定して記述されるべきだが、相当量のコンテンツが views 配列について誤った仮定を行い、その結果 2 つを超えるビューが提示されたときに壊れることが予想される。

ユーザーエージェントは、コンテンツの代わりにこれらの secondary views に レンダリングするために再投影のような仕組みを使用できる場合があるため、これらの secondary views を 自ら扱うことを計画しているコンテンツと、そのような secondary views の存在を認識していない、 または扱いたくないコンテンツとを区別できることが望ましい。

これを提供するため、secondary views を公開するユーザーエージェントは、ヒントとして "secondary-views" feature descriptor をサポートしなければならない。 この機能を有効にするコンテンツは、次を行うことが期待される:

"secondary-views" が有効な場合、ユーザーエージェントは 必要に応じて、デバイスがサポートする任意の secondary viewsXRSession に 提示してもよい。そのような場合、ユーザーエージェントは再投影を用いて secondary views を再構築してはならず、代わりに コンテンツがレンダリングすると決めたものに依存する。

注: 最大限の互換性を確保するため、コンテンツは "secondary-views" を有効にするために optionalFeatures を使用することを推奨する。

secondary views がより低い 基盤フレームレートを持つ場合、XRSession は 次の 1 つ以上を行うことを選んでもよい:

7.4. XRViewport

XRViewport オブジェクトは、グラフィックスサーフェスのビューポート、すなわち矩形領域を記述する。

[SecureContext, Exposed=Window] interface XRViewport {
  readonly attribute long x;
  readonly attribute long y;
  readonly attribute long width;
  readonly attribute long height;
};

x および y 属性はサーフェス原点からのオフセットを定義し、 width および height 属性はビューポートの矩形寸法を定義する。

ビューポート値の正確な解釈は、そのビューポートが関連付けられているグラフィックス API の規約に依存する:

次のコードは、XRViewerPose のすべての XRView をループし、 それぞれについて XRWebGLLayer から XRViewport を問い合わせ、それらを使用してレンダリングに適切な WebGL viewport を設定する。
xrSession.requestAnimationFrame((time, xrFrame) => {
  const viewer = xrFrame.getViewerPose(xrReferenceSpace);

  gl.bindFramebuffer(xrWebGLLayer.framebuffer);
  for (xrView of viewer.views) {
    let xrViewport = xrWebGLLayer.getViewport(xrView);
    gl.viewport(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height);

    // WebGL draw calls will now be rendered into the appropriate viewport.
  }
});

8. 幾何プリミティブ

8.1. 行列

WebXR は、matrices の形でさまざまな変換を提供する。 WebXR は行列を通信する際に WebGL の規約を使用し、そこでは 4x4 行列が列優先格納の 16 要素 Float32Array として与えられ、左から行列を前乗算することによって列ベクトルに適用される。これらは WebGL の uniformMatrix4fv 関数に直接渡すことができ、等価な DOMMatrix の作成に使用したり、さまざまなサードパーティの数学ライブラリで使用したりできる。

WebXR Device API から返される行列は、次のように並べられた 16 要素の Float32Array になる:
[a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15]

この行列を、次のように DOMPointReadOnly として指定された列ベクトルへの変換として適用すると:

{x:X, y:Y, z:Z, w:1}

次の結果を生成する:

a0 a4 a8  a12  *  X  =  a0 * X + a4 * Y +  a8 * Z + a12
a1 a5 a9  a13     Y     a1 * X + a5 * Y +  a9 * Z + a13
a2 a6 a10 a14     Z     a2 * X + a6 * Y + a10 * Z + a14
a3 a7 a11 a15     1     a3 * X + a7 * Y + a11 * Z + a15

8.2. 正規化

ベクトルまたはクォータニオンを正規化することを求めるアルゴリズムがいくつかある。これは、成分をスケールして、 合計の大きさが 1.0 になるようにすることを意味する。

成分のリストを 正規化するには、 UA は次の手順を実行しなければならない:

  1. length を各成分の二乗の和の平方根とする。

  2. length0 である場合、InvalidStateError を投げ、これらの手順を中止する。

  3. 各成分を length で除算し、その成分を設定する。

8.3. XRRigidTransform

XRRigidTransform は、positionorientation によって記述される変換である。XRRigidTransform を解釈する際、orientation は常に position より前に適用される。

XRRigidTransform は、matrix である internal matrix を含む。

[SecureContext, Exposed=Window]
interface XRRigidTransform {
  constructor(optional DOMPointInit position = {}, optional DOMPointInit orientation = {});
  [SameObject] readonly attribute DOMPointReadOnly position;
  [SameObject] readonly attribute DOMPointReadOnly orientation;
  readonly attribute Float32Array matrix;
  [SameObject] readonly attribute XRRigidTransform inverse;
};

XRRigidTransform(position, orientation) コンストラクターは、呼び出されたとき次の手順を実行しなければならない:

  1. transform新しい XRRigidTransform とし、現在のレルム内に作成する。

  2. transformposition を、現在のレルム内の 新しい DOMPointReadOnly とする。

  3. positionw 値が 1.0 でない場合、TypeError を投げ、これらの手順を中止する。

  4. position または orientation の値の 1 つ以上が NaN、 または infinity のような別の有限でない数である場合、TypeError を投げ、これらの手順を中止する。

  5. transformpositionx 値を position の x 辞書メンバーに、y 値を position の y 辞書メンバーに、z 値を position の z 辞書メンバーに、そして w 値を position の w 辞書メンバーに設定する。

  6. transformorientation を、現在のレルム内の 新しい DOMPointReadOnly とする。

  7. transformorientationx 値を orientation の x 辞書メンバーに、y 値を orientation の y 辞書メンバーに、z 値を orientation の z 辞書メンバーに、そして w 値を orientation の w 辞書メンバーに設定する。

  8. transforminternal matrixnull とする。

  9. transformorientationx, y, z, および w 成分を 正規化する。

  10. transform を返す。

position 属性は、変換の並進成分を記述する、 メートル単位で与えられる 3 次元点である。positionw 属性は 1.0 でなければならない。

orientation 属性は、変換の回転成分を記述する クォータニオンである。orientation は、長さが 1.0 になるよう正規化されなければならない。

matrix 属性は、position および orientation 属性によって記述される変換を matrix として返す。 この属性は、XRRigidTransformmatrix を取得することによって計算されなければならない。

注: この行列は、列ベクトルに前乗算されると、そのベクトルを orientation によって記述される 3D 回転で回転し、その後 position によって並進する。数学的には列ベクトル表記で、これは M = T * R であり、Tposition に対応する並進行列で、Rorientation に対応する回転行列である。

与えられた XRRigidTransform transform について matrix を取得するには:

  1. transforminternal matrixnull でない場合、 次の手順を実行する:

    1. internal matrix に対する IsDetachedBuffer 操作が false である場合、transforminternal matrix を返す。

  2. translation を、position に対応する列ベクトル並進行列である新しい matrix とする。数学的には、position(x, y, z) である場合、この行列は次のとおりである

    列ベクトル並進行列の数式

  3. rotation を、orientation に対応する列ベクトル回転行列である新しい matrix とする。数学的には、orientation が単位クォータニオン (qx, qy, qz, qw) である場合、 この行列は次のとおりである

    列ベクトル回転行列の数式

  4. transforminternal matrix を、 translationrotationtranslation を左側にして 乗算した結果(translation * rotation)に設定された、transform関連するレルム内の 新しい Float32Array に設定する。これは transform関連するレルム内で行う。 数学的には、この行列は次のとおりである

    左側に並進を置いて並進と回転を乗算した行列の数式

  5. transforminternal matrix を返す。

XRRigidTransform transforminverse 属性は、transform の関連するレルム内の XRRigidTransform を返す。これは、以前に transform によって変換されたオブジェクトに適用された場合、その変換を 元に戻し、オブジェクトを初期ポーズへ戻す。この属性は遅延評価されるべきである。inverse によって返される XRRigidTransform は、その inverse として transform を返さなければならない。

XRRigidTransform で、position{ x: 0, y: 0, z: 0 w: 1 }orientation{ x: 0, y: 0, z: 0, w: 1 } であるものは、identity transform として知られる。

BA という 2 つの XRRigidTransform を、Realm realm 内で 乗算するには、UA は次の手順を実行しなければならない:

  1. resultrealm 内の 新しい XRRigidTransform オブジェクトとする。

  2. resultmatrix を、Bmatrix を左から Amatrix に前乗算した結果である、realm 内の 新しい Float32Array に設定する。

  3. resultorientation を、resultmatrix の左上 3x3 部分行列が示す回転を記述するクォータニオンである、realm 内の 新しい DOMPointReadOnly に設定する。

  4. resultposition を、resultmatrix の第 4 列によって与えられるベクトルである、realm 内の 新しい DOMPointReadOnly に設定する。

  5. result を返す。

result は、A の source space から B の destination space への変換である。

注: これは、XRRigidTransform を構築することと等価である。その orientationAB の orientation の合成であり、その positionApositionBorientation で回転し、Bposition に加えたものと等しい。

9. ポーズ

9.1. XRPose

XRPose は、 XRSpace に相対する 空間内の位置と向きを記述する。

[SecureContext, Exposed=Window] interface XRPose {
  [SameObject] readonly attribute XRRigidTransform transform;
  [SameObject] readonly attribute DOMPointReadOnly? linearVelocity;
  [SameObject] readonly attribute DOMPointReadOnly? angularVelocity;

  readonly attribute boolean emulatedPosition;
};

transform 属性は、基準となる XRSpace に 相対する位置と向きを記述する。

linearVelocity 属性は、基準となる XRSpace に 相対する、メートル毎秒単位の線速度を記述する。ユーザーエージェントがこれを埋められない場合、 null を返すことが許される。

angularVelocity 属性は、基準となる XRSpace に 相対する、ラジアン毎秒単位の角速度を記述する。ユーザーエージェントがこれを埋められない場合、 null を返すことが許される。

emulatedPosition 属性は、transform がセンサー読み取りに基づく能動的にトラッキングされた 6DoF ポーズを表す場合は false であり、その position 値に、首モデルや腕モデルによって提供されるような computed offset が含まれる場合は true である。 Estimated floor level は、XRPosecomputed offset を含むかどうかを判断する際に考慮されてはならない。

9.2. XRViewerPose

XRViewerPose は、XRPose であり、 XR device によってトラッキングされる XR シーンの viewer の状態を記述する。viewer は、トラッキングされたハードウェアの一部、ハードウェアに 相対するユーザーの観測位置、または XR シーンへの一連の視点を計算するその他の手段を表しうる。XRViewerPose は、 XRReferenceSpace に相対してのみ問い合わせることができる。これは、XRPose 値に加えて、 視点と投影行列を示す剛体変換を含む view の 配列を提供する。これらの値は、XR シーンのフレームをレンダリングするときにアプリケーションによって 使用されるべきである。

[SecureContext, Exposed=Window] interface XRViewerPose : XRPose {
  [SameObject] readonly attribute FrozenArray<XRView> views;
};

views 配列は、XR シーンの視点を記述する XRView の列であり、 XRViewerPose が問い合わせられた XRReferenceSpace に相対している。配列内の XR シーンのすべての view は、 XR device 上で正しく表示するために レンダリングされなければならない。各 XRView は視点と 投影行列を示す剛体変換を含み、必要に応じてレイヤーから XRViewport を 問い合わせるために使用できる。

注: XRViewerPosetransform は、シーンの観客ビューまたはマルチユーザーインタラクションのために、viewer のグラフィカル表現を配置するために使用できる。

10. 输入

10.1. XRInputSource

XRInputSource 表示一个 XR 输入 源,它是任何允许用户在与观看者相同的 虚拟空间中执行定向操作的输入机制。XR 输入源的示例 包括但不限于手持控制器、光学跟踪的手,以及基于注视、并基于观看者姿态 运行的输入方法。未明确关联到 XR 设备的输入机制,例如传统游戏手柄、鼠标或键盘,SHOULD NOT 被 视为 XR 输入 源

enum XRHandedness {
  "none",
  "left",
  "right"
};

enum XRTargetRayMode {
  "gaze",
  "tracked-pointer",
  "screen",
  "transient-pointer"
};

[SecureContext, Exposed=Window]
interface XRInputSource {
  readonly attribute XRHandedness handedness;
  readonly attribute XRTargetRayMode targetRayMode;
  [SameObject] readonly attribute XRSpace targetRaySpace;
  [SameObject] readonly attribute XRSpace? gripSpace;
  [SameObject] readonly attribute FrozenArray<DOMString> profiles;
  readonly attribute boolean skipRendering;
};

注:XRInputSource 接口也由 WebXR 游戏手柄 模块扩展

handedness 属性描述该 XR 输入源关联到哪只手, 如果有关联的话。没有自然 handedness 的输入源(例如头显安装的控制器),或当前 handedness 未知的输入源, MUST 将此属性设为 "none"

targetRayMode 属性描述用于生成目标射线的方法, 并指示应用在需要时应如何向用户呈现目标射线。

targetRaySpace 属性是一个 XRSpace,它具有一个 native origin, 跟踪该 XRInputSource 的首选指向射线的位置和朝向(沿其 -Z 轴),如 targetRayMode 所定义。

对于 targetRayMode"transient-pointer" 的输入源,targetRaySpace 表示交互开始时指向交互目标的射线。其姿态应在此 XRInput 的 gripSpace 内保持静态。

gripSpace 属性是一个 XRSpace,它具有一个 native origin, 跟踪应当用于渲染虚拟对象的姿态,使这些对象看起来像被握在用户手中。如果用户握着一根直杆,则此 XRSpacenative origin 放在其弯曲手指的质心处,并使 -Z 轴沿着杆的长度指向其拇指。X 轴垂直于所描述的手背, 用户右手手背指向 +X,用户左手手背指向 -XY 轴由 XZ 轴之间的关系隐含,其中 +Y 大致指向用户手臂的方向。

skipRendering 属性指示此输入是可见的,并且 MAY NOT 需要由当前会话渲染。如果 skipRendering 为 true 且 targetRayMode 为 "tracked-pointer",则用户代理 MUST 确保始终向用户显示该 XR 输入源的表示。

向用户显示控制器的示例包括控制器位于显示器和用户之间、显示器是透明的,或控制器由操作系统渲染。

skipRendering 是给开发者的提示,表示不要渲染控制器等输入源。拾取射线和光标仍应被渲染。

对于 targetRayMode"transient-pointer" 的输入源,如果存在关联的用户手势,则 gripSpace 应为该关联用户手势,否则应为用户控制的另一个空间,例如 ViewerSpace,或另一个 XRInput 的 gripSpace 或 targetRaySpace。这样做是为了允许用户仍然操纵 targetRaySpace。

如果输入源并非固有可跟踪,例如 targetRayMode"gaze""screen" 的输入源,则 gripSpace MUST 为 null

profiles 属性是一个列表,包含若干 输入配置文件 名称,用于指示输入源的首选视觉表示和行为。

输入配置文件名称是一个 ASCII 小写的 DOMString, 不包含空格,并用连字符(-)连接分隔的单词。应选择描述性名称,并尽可能使用设备供应商首选的措辞。 如果平台提供了适当的标识符,例如 USB 供应商和产品 ID,则 MAY 使用它。MUST NOT 使用唯一标识单个设备的值, 例如序列号。输入配置文件名称 MUST NOT 包含设备 handedness 的指示。 如果多个用户代理暴露同一设备,它们 SHOULD 努力报告相同的 输入配置文件名称WebXR 输入 配置文件注册表是管理输入配置文件 名称的推荐位置。

Profiles 按具体性降序给出。列表中第一个条目之后给出的任何输入配置文件 名称都应提供 fallback 值,表示设备的替代表示。这可以包括设备的更通用或先前版本、足够相似且更广泛认可的设备, 或设备类型的宽泛描述(例如 "generic-trigger-touchpad")。如果给出多个 profiles,则它们描述的布局必须都表示 列表中其他每个 profile 的超集或子集。

如果 XRSession 是 一个内联会话,则 profiles MUST 是一个空列表。

用户代理 MAY 自行决定只报告适当的通用输入配置文件 名称或空列表。适合这样做的一些场景包括:输入设备无法被可靠识别、没有已知输入 profiles 与输入设备匹配, 或用户代理希望掩盖正在使用的输入设备。

例如,Samsung HMD Odyssey 的控制器是标准 Windows Mixed Reality 控制器的设计变体。两个控制器共享相同的输入布局。 因此,Samsung HMD Odyssey 控制器的 profiles 可以是: ["samsung-odyssey", "microsoft-mixed-reality", "generic-trigger-squeeze-touchpad-thumbstick"]。 控制器外观由列表中的第一个 profile 最精确地传达,第二个 profile 描述可接受的替代项,最后一个 profile 是通用 fallback,以最粗略的意义描述该设备。(它是一个带有扳机、握压按钮、触摸板和摇杆的控制器。)
同样,Valve Index 控制器向后兼容 HTC Vive 控制器,但 Index 控制器有额外的按钮和轴。因此,Valve Index 控制器的 profiles 可以是: ["valve-index", "htc-vive", "generic-trigger-squeeze-touchpad-thumbstick"]。在这种情况下, "valve-index" profile 描述的输入布局是 "htc-vive" profile 描述的布局的超集。 此外,"valve-index" profile 指示控制器的精确外观,而 "htc-vive" 控制器具有显著不同的外观。 在这种情况下,UA 会认为这种差异是可接受的。并且与第一个示例一样,最后一个 profile 是通用 fallback。
(确切字符串仅为示例。实际 profile 名称在 WebXR 输入 配置文件注册表中管理。)

注:XRInputSourceXRSessioninputSources 数组中是“live”的。因此,它们内部的值会被就地更新。这意味着保存某一帧上 XRInputSource 的 属性引用,并在后续帧中将其与同一属性比较以测试状态变化,是不可行的,因为它们将是同一个对象。因此, 希望逐帧比较输入状态的开发者应复制相关状态的内容。

如果一个 XR 输入源 支持 主要操作, 则它是一个 主要输入 源主要操作是一种平台特定操作,当其被触发时,会产生 selectstartselectendselect 事件。可能的主要操作示例包括按下扳机、触摸板或按钮,说出命令,或做出手势。如果平台指南定义了推荐的 主要输入,则应将其用作主要 操作,否则用户代理可自由选择一个。设备 MUST 支持至少一个主要输入 源

如果一个 XR 输入源不支持 主要操作,则它是一个 被跟踪输入 源。这些输入主要旨在提供姿态数据。 注:被跟踪输入源的一个示例是用于用户腿部或道具的跟踪附件。如果未执行手势识别来检测 主要 操作,则被跟踪的手也可被视为被跟踪输入源

XRSession session 的一个 XR 输入 源 source 开始其主要操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以触发输入 源事件,其名称为 selectstart, frame 为 frame,source 为 source

XRSession session 的一个 XR 输入 源 source 结束其主要操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以执行以下步骤:

    1. 触发输入源事件,其名称为 select, frame 为 frame,source 为 source

    2. 触发输入源事件,其名称为 selectend, frame 为 frame,source 为 source

每个 XR 输入源 MAY 定义一个 主要 squeeze 操作主要 squeeze 操作是一种平台特定操作,当其被触发时,会产生 squeezestartsqueezeendsqueeze 事件。主要 squeeze 操作应用于大致映射为挤压或抓取的操作。可能的 主要 squeeze 操作示例包括 按下 grip trigger 或做出抓取手势。如果平台指南定义了推荐的主要 squeeze 操作,则应将其用作 主要 squeeze 操作,否则用户代理 MAY 选择一个。

XRSession session 的一个 XR 输入 源 source 开始其主要 squeeze 操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以触发输入 源事件,其名称为 squeezestart, frame 为 frame,source 为 source

XRSession session 的一个 XR 输入 源 source 结束其主要 squeeze 操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以执行以下步骤:

    1. 触发输入源事件,其名称为 squeeze, frame 为 frame,source 为 source

    2. 触发输入源事件,其名称为 squeezeend, frame 为 frame,source 为 source

有时,平台特定行为可能导致主要操作主要 squeeze 操作被 中断或取消。例如,一个 XR 输入源可能在主要操作主要 squeeze 操作开始之后、结束之前,从 XR 设备中被移除。

XRSession session 的一个 XR 输入 源 source主要操作被取消时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以触发输入 源事件,触发一个名称为 selectendXRInputSourceEvent, frame 为 frame,source 为 source

XRSession session 的一个 XR 输入 源 source主要 squeeze 操作被取消时,UA MUST 运行以下 步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsessiontime 为该操作发生的时间。

  2. 排队一个任务,以触发输入 源事件,触发一个名称为 squeezeendXRInputSourceEvent, frame 为 frame,source 为 source

10.2. 瞬态输入

一些 XR 设备可能支持 瞬态输入 源,其中 XR 输入源只有在执行一个 瞬态操作时才有意义, 该操作可以是 主要操作 (针对主要输入 源),也可以是设备特定的 辅助操作(针对被跟踪输入源)。

一个示例是针对内联会话的鼠标、触摸或触控笔输入,它 MUST 产生一个瞬态 XRInputSource, 其 targetRayMode 设为 screen, 并被视为主要操作 (针对 主指针),以及非主指针的非主要 辅助操作

另一个示例是来自操作系统的意图,其输入派生自无法直接暴露的敏感信息,例如基于注视的交互。这些会产生一个瞬态 XRInputSource, 其 targetRayMode 设为 transient-pointer, 并被视为主要 操作

瞬态输入 源只在瞬态操作持续期间存在于会话的 活动 XR 输入源列表中。

瞬态输入 源在处理瞬态操作时遵循以下序列,而不是用于非瞬态 主要操作的算法:

XRSession session 的一个 瞬态输入源 source 开始其 瞬态操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsession,时间为该操作发生的时间。

  2. 排队一个任务,以执行以下步骤:

    1. 如有必要,触发由 XR 输入源操作产生的任何 "pointerdown" 事件。

    2. XR 输入源添加活动 XR 输入源列表

    3. 如果 瞬态操作是一个 主要操作,则触发输入源事件,其名称为 selectstart, frame 为 frame,source 为 source

XRSession session 的一个 瞬态输入源 source 结束其 瞬态操作时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsession,时间为该操作发生的时间。

  2. 排队一个任务,以执行以下步骤:

    1. 如果 瞬态操作是一个 主要操作,则触发输入源事件,其名称为 select, frame 为 frame,source 为 source

    2. 如有必要,触发由 XR 输入源操作产生的任何 "click" 事件。

    3. 如果 瞬态操作是一个 主要操作,则触发输入源事件,其名称为 selectend, frame 为 frame,source 为 source

    4. 活动 XR 输入源列表移除 XR 输入源

    5. 如有必要,触发由 XR 输入源操作产生的任何 "pointerup" 事件。

XRSession session 的一个 瞬态输入源 source瞬态操作被取消时,UA MUST 运行以下步骤:

  1. framesession相关 realm中的一个 XRFrame, 其 sessionsession,时间为该操作发生的时间。

  2. 排队一个任务,以执行以下步骤:

    1. 如果 瞬态操作是一个 主要操作,则触发输入源事件,其名称为 selectend, frame 为 frame,source 为 source

    2. 活动 XR 输入源列表移除 XR 输入源

    3. 如有必要,触发由 XR 输入源操作产生的任何 "pointerup" 事件。

10.3. XRInputSourceArray

XRInputSourceArray 表示一个由 XRInputSource 组成的列表。 当列表内容预期会随时间变化时使用它, 而不是使用 冻结 数组类型,例如 XRSessioninputSources 属性。

[SecureContext, Exposed=Window]
interface XRInputSourceArray {
  iterable<XRInputSource>;
  readonly attribute unsigned long length;
  getter XRInputSource(unsigned long index);
};

XRInputSourceArraylength 属性指示该 XRInputSourceArray 中包含多少个 XRInputSource

XRInputSourceArray索引属性 getter 会检索所提供索引处的 XRInputSource

11.

注:虽然本规范只定义了 XRWebGLLayer 层,但预计规范的未来扩展会添加更多层类型以及它们所绘制的图像源。

11.1. XRLayer

[SecureContext, Exposed=Window]
interface XRLayer : EventTarget {};

XRLayerXRWebGLLayer 和未来扩展引入的其他层类型的基类。

11.2. XRWebGLLayer

XRWebGLLayer 是一个提供 WebGL framebuffer 以供渲染的层,使硬件加速的 3D 图形渲染能够呈现在 XR 设备上。

typedef (WebGLRenderingContext or
         WebGL2RenderingContext) XRWebGLRenderingContext;

dictionary XRWebGLLayerInit {
  boolean antialias = true;
  boolean depth = true;
  boolean stencil = false;
  boolean alpha = true;
  boolean ignoreDepthValues = false;
  double framebufferScaleFactor = 1.0;
};

[SecureContext, Exposed=Window]
interface XRWebGLLayer: XRLayer {
  constructor(XRSession session,
             XRWebGLRenderingContext context,
             optional XRWebGLLayerInit layerInit = {});
  // Attributes
  readonly attribute boolean antialias;
  readonly attribute boolean ignoreDepthValues;
  attribute float? fixedFoveation;

  [SameObject] readonly attribute WebGLFramebuffer? framebuffer;
  readonly attribute unsigned long framebufferWidth;
  readonly attribute unsigned long framebufferHeight;

  // Methods
  XRViewport? getViewport(XRView view);

  // Static Methods
  static double getNativeFramebufferScaleFactor(XRSession session);
};

每个 XRWebGLLayer 都有一个 context 对象,初始为 null,它是 WebGLRenderingContextWebGL2RenderingContext 的实例。

每个 XRWebGLLayer 都有关联的 session,它是创建该对象时所用的 XRSession

XRWebGLLayer(session, context, layerInit) 构造函数在调用时 MUST 执行以下步骤:

  1. layersession相关 realm中的一个 XRWebGLLayer

  2. 如果 sessionended 值为 true,则抛出 InvalidStateError 并中止这些步骤。

  3. 如果 context is lost,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 session 是一个沉浸式会话,并且 contextXR compatible 布尔值为 false,则抛出 InvalidStateError 并中止这些步骤。

  5. layercontext 初始化为 context

  6. layersession 初始化为 session

  7. 按如下方式初始化 layerignoreDepthValues

    如果 layerInitignoreDepthValues 值为 falseXR Compositor 将使用深度值:

    layerignoreDepthValues 初始化为 false

    否则:

    layerignoreDepthValues 初始化为 true

  8. 按如下方式初始化 layercomposition enabled 布尔值:

    如果 session 是一个内联会话

    layercomposition enabled 初始化为 false

    否则:

    layercomposition enabled 布尔值初始化为 true

  9. 如果 layercomposition enabled 布尔值为 true
    1. layerantialias 初始化为 layerInitantialias 值。

    2. scaleFactorlayerInitframebufferScaleFactor

    3. 用户代理 MAY 在此处选择按其认为合适的方式钳制或舍入 scaleFactor, 例如,如果它出于性能原因希望将缓冲区尺寸适配为 2 的幂。

    4. framebufferSize推荐的 WebGL framebuffer 分辨率,其宽度和高度分别乘以 scaleFactor

    5. layerframebuffer 初始化为 context相关 realm中的一个 WebGLFramebuffer, 它是一个由 context 创建、尺寸为 framebufferSize不透明 framebuffer,其 session 初始化为 session,并使用 layerInitdepthstencilalpha 值。

    6. 根据支持 layer 合成的需要,分配并初始化与 sessionXR 设备兼容的资源,包括 GPU 可访问 内存缓冲区。

    7. 如果 layer 的资源因任何原因无法创建,则抛出 OperationError 并中止这些步骤。

    否则:
    1. layerantialias 初始化为 layercontext实际上下文参数中的 antialias 值。

    2. layerframebuffer 初始化为 null

  10. 返回 layer

注:如果一个 XRWebGLLayercomposition enabled 布尔值被设为 false,则 XRWebGLLayerInit 对象上的所有值都会被忽略,因为 WebGLRenderingContext 的 默认 framebuffer 已经使用上下文的实际上下文参数分配,且不能被覆盖。

context 属性是创建该 XRWebGLLayer 时所用的 WebGLRenderingContext

每个 XRWebGLLayer 都有一个 composition enabled 布尔值,初始设为 true。如果设为 false,则表示该 XRWebGLLayer MUST NOT 分配自己的 WebGLFramebuffer, 并且 XRWebGLLayer 上所有反映 framebuffer 属性的属性 MUST 改为反映 context 的默认 framebuffer 的属性。

XRWebGLLayerframebuffer 属性是一个 WebGLFramebuffer 实例;如果 composition enabledtrue,它已被标记为不透明,否则为 null。在 XRWebGLLayer 创建之后,开发者不能调整 framebuffer 大小。

不透明 framebuffer 的功能与标准 WebGLFramebuffer 相同,但有以下更改,使其行为更像默认 framebuffer

注:用户代理需要尊重 depthstenciltrue 值,这类似于 WebGL 在创建绘图缓冲区时的行为。

附加到不透明 framebuffer的缓冲区 MUST 在首次创建时,或在处理每个 XR 动画帧之前,被清除为下表中的值。 这与 WebGL 上下文的默认 framebuffer行为相同。无论关联 WebGL 上下文的 preserveDrawingBuffer 值如何,不透明 framebuffers 都将始终被清除。

缓冲区 清除值
颜色 (0, 0, 0, 0)
深度 1.0
模板 0

注:实现可以优化掉不透明 framebuffer所需的隐式清除操作,只要能保证开发者无法访问来自另一进程的 缓冲区内容。例如,如果开发者执行了显式清除,则不需要隐式清除。

如果一个 XRWebGLLayer 创建时 alpha 被设为 true,则 framebuffer 必须由具有 RGBA 颜色格式的纹理支持。 如果一个 XRWebGLLayer 创建时 alpha 被设为 false,则 framebuffer 必须由具有 RGB 颜色格式的纹理支持。

但是,XR Compositor MUST 将 framebuffer 的 backing 像素视为处于 SRGB8_ALPHA8SRGB8 colorFormat 中。

注:这意味着 XR Compositor 在处理作为 framebuffer backing 的纹理时,MUST 不对线性 RGBARGB 执行任何 gamma 转换。否则,最终渲染中的像素会显得过亮,这将与常规 2D WebGLRenderingContext 上下文中的渲染不匹配。

当一个 XRWebGLLayer 被设置为一个沉浸式 会话baseLayer 时,不透明 framebuffer 的内容会在一个 XR 动画 帧完成后立即呈现给 沉浸式 XR 设备,但仅当自前一个 XR 动画帧以来至少发生以下任一情况:

不透明 framebuffer呈现给沉浸式 XR 设备之前,用户代理应确保所有渲染操作都已刷新到 不透明 framebuffer

每个 XRWebGLLayer 都有一个 target framebuffer,如果 composition enabledtrue,它就是 framebuffer, 否则是 context 的 默认 framebuffer。

framebufferWidthframebufferHeight 属性分别返回 target framebuffer 附件的宽度和高度。

antialias 属性在 target framebuffer 使用 UA 选择的技术支持抗锯齿时为 true,如果不会执行抗锯齿则为 false

ignoreDepthValues 属性如果为 true,则表示 XR Compositor MUST NOT 在渲染时使用深度缓冲区附件中的值。 当该属性为 false 时,表示深度缓冲区附件的内容将由 XR Compositor 使用,并预期能代表渲染到该层中的场景。

存储在缓冲区中的深度值预期位于 0.01.0 之间,其中 0.0 表示 depthNear 的距离,1.0 表示 depthFar 的距离,中间值线性插值。这是 WebGL 的默认行为。(更多细节见 depthRange 函数文档。)

注:使场景的深度缓冲区可供 compositor 使用,可允许某些平台提供质量和舒适度改进, 例如改进的重投影。

fixedFoveation 属性控制 XR Compositor 使用的 foveation 量。如果用户代理或设备不支持此属性,它们在获取时应返回 null,设置时应为 no-op。将 fixedFoveation 设为小于 0 的值会将其设为 0,设为大于 1 的值会将其设为 10 设置最小的 foveation 量,而 1 设置最大值。XR Compositor 如何解释这些值由用户代理决定。 如果 fixedFoveation 级别发生变化,它将在下一个 XRFrame 生效。

注:Fixed foveation 是一种降低用户视场边缘附近内容渲染分辨率的技术。 它可以显著改善受限于 GPU 填充性能的体验。它会降低功耗,并使应用能够提高眼部纹理的分辨率。它最适用于低对比度纹理, 例如背景图像,而较不适用于高对比度内容,例如文本或详细图像。作者可以按帧调整级别,以实现性能和视觉质量之间的最佳权衡。

每个 XRWebGLLayer MUST 有一个 完整大小视口列表,它是一个列表,包含一个 WebGL viewport,对应 XRSession 可能暴露的每个 视图,包括当前未活动但可能在当前会话中变为 活动次 视图。这些视口 MUST 具有大于 0widthheight, 并且 MUST 描述一个不超过 target framebuffer 边界的矩形。这些视口 MUST NOT 重叠。

如果 composition enabledfalse,且 session视图 列表包含单个 视图,其 eye"none", 则 完整大小视口列表 MUST 包含单个 WebGL viewport,覆盖 context 的整个默认 framebuffer。

如果 composition enabledfalse,且 session视图 列表包含两个主 视图,其中一个的 eye"left", 另一个的 eye"right", 则 完整大小视口列表 MUST 包含两个 WebGL viewport:一个关联到 "left" 视图,另一个关联到 "right" 视图。用户代理在受上述约束限制的情况下确定这些视口的大小和 位置。

注:本规范不要求立体内联视口采用特定打包方式,例如并排排列。 作者应为每个 XRView 使用 getViewport(), 而不是假定某种布局。

每个 XRWebGLLayer MUST 有一个 视口对象 列表,它是一个列表,包含一个 XRViewport, 对应 XRSession 当前暴露的每个活动 视图

getViewport() 查询给定 XRView 在渲染到该层时应使用的 XRViewport

getViewport(view) 方法在 XRWebGLLayer layer 上调用时,MUST 运行以下步骤:

  1. sessionviewsession

  2. framesessionanimation frame

  3. 如果 session 不等于 layersession,则抛出 InvalidStateError 并中止这些步骤。

  4. 如果 frameactive 布尔值为 false,则抛出 InvalidStateError 并中止这些步骤。

  5. 如果 viewframe 不等于 frame,则抛出 InvalidStateError 并中止这些步骤。

  6. 如果 viewport modifiable 标志为 true,且 viewrequested viewport scale 不等于 current viewport scale

    1. current viewport scale 设置为 requested viewport scale

    2. 视口对象列表中,将与 view 关联的 XRViewport 设为从与 sessionview 关联的 完整大小视口列表获得缩放视口所得的 XRViewport 结果。

  7. viewviewport modifiable 标志设为 false。

  8. viewport视口对象列表中与 view 关联的 XRViewport

  9. 返回 viewport

注:viewport modifiable 标志会被有意设为 false, 即使 current viewport scale 没有变化也是如此。这确保 getViewport(view) 调用在一个动画帧内对于该视图总是返回一致的结果, 因此第一个检索到的值会在该帧剩余期间被锁定。如果应用在 getViewport() 之后调用 requestViewportScale(), 则请求的值只会在未来帧中再次调用 getViewport() 时才被应用。

每个 XRSession MUST 标识一个 原生 WebGL framebuffer 分辨率,即为匹配 XR 设备的物理像素分辨率而需要的 WebGL framebuffer 像素分辨率。

一个 XRSession session原生 WebGL framebuffer 分辨率通过运行以下步骤确定:

  1. 如果 session 是一个内联会话,则将 原生 WebGL framebuffer 分辨率设为 sessionrenderStateoutput canvas 的物理显示像素大小, 每次 canvas 大小发生变化或output canvas 发生变化时重新评估这些步骤,并中止这些步骤。

  2. 原生 WebGL framebuffer 分辨率设为如下所需的分辨率: 一个足够大、能够包含会话所有 XRView 的 framebuffer 的像素,与最高放大倍率下显示区域中的物理屏幕像素之间具有 1:1 比率。如果不存在如上所述确定原生分辨率的方法, MAY 使用 推荐的 WebGL framebuffer 分辨率

此外,XRSession MUST 标识一个 推荐的 WebGL framebuffer 分辨率,它表示一个最佳估计的 WebGL framebuffer 分辨率:足够大以包含会话所有 XRView, 并为普通应用在性能和质量之间提供良好平衡。它 MAY 小于、大于或等于 原生 WebGL framebuffer 分辨率。新的 不透明 framebuffer 将使用此分辨率创建,其宽度和高度分别按任何所提供的 XRWebGLLayerInitframebufferScaleFactor 缩放。

注:用户代理可自由使用其选择的任何方法来估计 推荐的 WebGL framebuffer 分辨率。如果存在用于查询推荐大小的平台特定方法, 建议使用它们,但并非必须。framebufferScaleFactorgetNativeFramebufferScaleFactor() 使用的缩放因子分别应用于宽度和高度,因此缩放因子为二会导致总体像素数变为四倍。如果平台暴露基于面积的渲染缩放, 且它基于像素数,则用户代理需要对其取平方根,以将其转换为 WebXR 缩放因子。

getNativeFramebufferScaleFactor(session) 方法在调用时 MUST 运行以下步骤:

  1. sessionthis

  2. 如果 sessionended 值为 true,则返回 0.0 并中止这些步骤。

  3. 返回一个值,使 session推荐的 WebGL framebuffer 分辨率的宽度和高度分别乘以该值后,得到 session原生 WebGL framebuffer 分辨率

11.3. WebGL コンテキスト互換性

WebGL コンテキストを没入型 XR 画像のソースとして使用するには、immersive XR device のための compatible graphics adapter 上で作成されなければならない。何が compatible graphics adapter とみなされるかはプラットフォーム依存であるが、過度な遅延なしにグラフィックスアダプターが immersive XR device へ画像を供給できることを意味すると理解される。 WebGL コンテキストがまだ compatible graphics adapter 上で作成されていない場合、通常は XRWebGLLayer とともに使用できるようになる前に、問題のアダプター上で再作成されなければならない。

注: 単一の GPU を持つ XR プラットフォームでは、その GPU が プラットフォームによって提示される immersive XR device と互換性があると安全に仮定でき、したがって ハードウェアアクセラレーションされた任意の WebGL コンテキストも互換性がある。統合 GPU とディスクリート GPU の 両方を持つ PC では、一般により高性能なチップであるため、ディスクリート GPU が compatible graphics adapter とみなされることが多い。 複数のグラフィックスアダプターがインストールされたデスクトップ PC では、immersive XR device が物理的に接続されているものが、compatible graphics adapter とみなされる可能性が高い。

注: Inline sessions は canvas と同じグラフィックスアダプターを使用して レンダリングするため、xrCompatible コンテキストを必要としない。

partial dictionary WebGLContextAttributes {
    boolean xrCompatible = false;
};

partial interface mixin WebGLRenderingContextBase {
    [NewObject] Promise<undefined> makeXRCompatible();
};

ユーザーエージェントがこの仕様を実装する場合、すべての WebGLRenderingContextBase 上に、初期値が false に設定された XR compatible 真偽値を設定しなければならない。 XR compatible 真偽値が true に設定されると、そのコンテキストは現在の immersive XR device から要求された任意の XRSession のレイヤーとともに使用できる。

注: このフラグは遅い同期的な振る舞いを導入するため、 推奨されない。非同期の解決策として、代わりに makeXRCompatible() を呼び出すことを検討すること。

XR compatible 真偽値は、 コンテキスト作成時、またはコンテキスト作成後のいずれかに設定でき、後者ではコンテキスト喪失が発生する可能性がある。 コンテキスト作成時に XR compatible 真偽値を設定するには、WebGL コンテキストを要求するときに xrCompatible コンテキスト作成属性を true に設定しなければならない。要求元文書の origin が "xr-spatial-tracking" permissions policy の使用を許可されていない場合、xrCompatible は効果を持たない。

xrCompatible フラグは、WebGLContextAttributes 上で true の場合、ユーザーエージェントに WebGL コンテキストを作成する際に、immersive XR device のための compatible graphics adapter を使用するよう要求することで、 コンテキスト作成に影響する。ユーザーエージェントがこれに成功した場合、作成されたコンテキストの XR compatible 真偽値は true に設定される。immersive XR device を取得するには、immersive XR device が選択されていることを保証する ことが呼び出されるべきである。

注: Immersive XR device が選択されていることを保証する並列に実行される必要があり、これはメインスレッド上に遅い同期的な振る舞いを導入する。 ユーザーエージェントは、代わりに makeXRCompatible() を使用するよう求める警告をコンソールに出力するべきである。

次のコードは、immersive XR device と互換性のある WebGL コンテキストを作成し、それを使用して XRWebGLLayer を作成する。
function onXRSessionStarted(xrSession) {
  const glCanvas = document.createElement("canvas");
  const gl = glCanvas.getContext("webgl", { xrCompatible: true });

  loadWebGLResources();

  xrSession.updateRenderState({ baseLayer: new XRWebGLLayer(xrSession, gl) });
}

コンテキストが作成された後に XR compatible 真偽値を設定するには、makeXRCompatible() メソッドが使用される。

注: 一部のシステムでは、このフラグによって、たとえば高出力の ディスクリート GPU が有効になったり、すべてのコマンドがデバイス上の GPU にプロキシされたりすることがある。 XR を使用するかどうか分からない状況にある場合は、immersive session を開始する意図があるときにのみ makeXRCompatible() を呼び出すことが提案される。

makeXRCompatible() メソッドは、WebGLRenderingContextBaseimmersive XR device のための compatible graphics adapter 上で実行されていることを保証する。

このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. 要求元文書の origin が "xr-spatial-tracking" permissions policy の使用を許可されていない場合、 promise解決し、 それを返す。XR permissions policy が無効な場合、この場合は XR device が存在しないかのように 振る舞いたい。なぜなら makeXRCompatible() は set-and-forget メソッドであることが想定されているためである。

  2. promise を、この WebGLRenderingContextBaseRealm 内で作成された 新しい Promise とする。

  3. contextthis とする。

  4. 次の手順を 並列に実行する:

    1. device を、immersive XR device が選択されていることを保証する結果とする。

    2. contextXR compatible 真偽値を次のように設定する:

      contextWebGL context lost flag が設定されている場合:

      contextXR compatible 真偽値を false に設定し、promiseInvalidStateError拒否するよう タスクをキューに入れる

      devicenull である場合:

      contextXR compatible 真偽値を false に設定し、promiseInvalidStateError拒否するよう タスクをキューに入れる

      contextXR compatible 真偽値が true である場合:

      promise解決するよう タスクをキューに入れる

      contextdevice のための compatible graphics adapter 上で 作成されていた場合:

      contextXR compatible 真偽値を true に設定し、promise解決するよう タスクをキューに入れる

      そうでない場合:

      次の手順を実行するよう、WebGL task source 上に タスクをキューに入れる:

      1. context を強制的に lost にする。

      2. WebGL 仕様で説明されるように、コンテキスト喪失を処理する:

        1. canvascontextcanvas とする。

        2. contextwebgl context lost flag が設定されている場合、これらの手順を中止する。

        3. contextwebgl context lost flag を設定する。

        4. context によって作成された各 WebGLObject インスタンスの invalidated フラグを設定する。

        5. "WEBGL_lose_context" を除くすべての拡張を無効にする。

        6. 次の手順を実行するよう、WebGL task source 上に タスクをキューに入れる:

          1. canvas に対して、statusMessage を "" に設定した、"webglcontextlost" という名前の e である WebGL コンテキストイベントを発火する。

          2. ecanceled flag が 設定されていない場合、promiseAbortError拒否し、これらの手順を中止する。

          3. 次の手順を 並列に実行する。

            1. device のための compatible graphics adapter 上の復元可能な drawing buffer を待つ。

            2. 次の手順を実行するよう、WebGL task source 上に タスクをキューに入れる:

              1. device のための compatible graphics adapter 上で コンテキストを復元する。

              2. contextXR compatible 真偽値を true に設定する。

              3. promise解決する。

  5. promise を返す。

さらに、任意の WebGL context が lost になったとき、"webglcontextlost" イベントを発火する前に、 次の手順を実行する:

  1. コンテキストの XR compatible 真偽値を false に設定する。

次のコードは、既存の WebGL コンテキストから XRWebGLLayer を作成する。
const glCanvas = document.createElement("canvas");
const gl = glCanvas.getContext("webgl");

loadWebGLResources();

glCanvas.addEventListener("webglcontextlost", (event) => {
  // WebGL コンテキストを復元できることを示す。
  event.canceled = true;
});

glCanvas.addEventListener("webglcontextrestored", (event) => {
  // コンテキスト喪失後は WebGL リソースを再作成する必要がある。
  loadWebGLResources();
});

async function onXRSessionStarted(xrSession) {
  // 使用したい canvas コンテキストがデバイスと互換性があることを確認する。
  // コンテキスト喪失を引き起こすことがある。
  await gl.makeXRCompatible();
  xrSession.updateRenderState({ baseLayer: new XRWebGLLayer(xrSession, gl) });
}

12. イベント

この仕様内で キューに入れられるすべての task source は、別段の指定がない限り、XR task source である。

12.1. XRSessionEvent

XRSessionEvent は、 XRSession の 状態の変化を示すために発火される。

[SecureContext, Exposed=Window]
interface XRSessionEvent : Event {
  constructor(DOMString type, XRSessionEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
};

dictionary XRSessionEventInit : EventInit {
  required XRSession session;
};

session 属性は、そのイベントを生成した XRSession を示す。

12.2. XRInputSourceEvent

XRInputSourceEvent は、 XRInputSource の状態の変化を示すために発火される。

[SecureContext, Exposed=Window]
interface XRInputSourceEvent : Event {
  constructor(DOMString type, XRInputSourceEventInit eventInitDict);
  [SameObject] readonly attribute XRFrame frame;
  [SameObject] readonly attribute XRInputSource inputSource;
};

dictionary XRInputSourceEventInit : EventInit {
  required XRFrame frame;
  required XRInputSource inputSource;
};

inputSource 属性は、このイベントを生成した XRInputSource を示す。

frame 属性は、イベントが発生した時刻に対応する XRFrame である。 これは履歴データを表すことがある。getViewerPose()frame 上で呼び出されたとき、例外を投げなければならない。

ユーザーエージェントが、名前 nameXRFrame frame、および XRInputSource source入力ソースイベントを発火する必要があるとき、次の手順を実行しなければならない:

  1. XRInputSourceEvent event を、type nameframe frame、および inputSource source で作成する。

  2. frameactive 真偽値を true に設定する。

  3. frame に対して frame updates を適用する。

  4. eventframesession 上で Dispatch する

  5. frameactive 真偽値を false に設定する。

12.3. XRInputSourcesChangeEvent

XRInputSourcesChangeEvent は、 XRSession が 利用できる アクティブな XR 入力ソースのリストの変化を示すために発火される。

[SecureContext, Exposed=Window]
interface XRInputSourcesChangeEvent : Event {
  constructor(DOMString type, XRInputSourcesChangeEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
  [SameObject] readonly attribute FrozenArray<XRInputSource> added;
  [SameObject] readonly attribute FrozenArray<XRInputSource> removed;
};

dictionary XRInputSourcesChangeEventInit : EventInit {
  required XRSession session;
  required sequence<XRInputSource> added;
  required sequence<XRInputSource> removed;

};

session 属性は、そのイベントを 生成した XRSession を示す。

added 属性は、イベント時に XRSession に 追加された XRInputSourcelist である。

removed 属性は、イベント時に XRSession から 削除された XRInputSourcelist である。

12.4. XRReferenceSpaceEvent

XRReferenceSpaceEvent は、 XRReferenceSpace の状態の変化を示すために発火される。

[SecureContext, Exposed=Window]
interface XRReferenceSpaceEvent : Event {
  constructor(DOMString type, XRReferenceSpaceEventInit eventInitDict);
  [SameObject] readonly attribute XRReferenceSpace referenceSpace;
  [SameObject] readonly attribute XRRigidTransform? transform;
};

dictionary XRReferenceSpaceEventInit : EventInit {
  required XRReferenceSpace referenceSpace;
  XRRigidTransform? transform = null;
};

referenceSpace 属性は、 このイベントを生成した XRReferenceSpace を示す。

任意の transform 属性は、イベント前の 座標系における referenceSpacenative origin の、イベント後の位置と向きを記述する。この属性は、XRSystem が 古い座標系と新しい座標系の間の差分を判断できない場合、null であってもよい。

注: referenceSpace または referenceSpace が生じうる状況は、ヘッドセットが 2 つの別々の場所の間で外され、装着された場合である。そのような場合、 体験が world-locked content に依存しているなら、ユーザーに警告し、シーンをリセットすべきである。

12.5. XRVisibilityMaskChangeEvent

フラスタムは矩形ディスプレイと正確に交差しないため、XRLayer の全領域が 表示されない場合がある。このイベントは、ユーザーに表示される XRView の領域を 体験に知らせる。

XRVisibilityMaskChangeEvent イベントは、ユーザーエージェントが、XRLayer の表示領域が 変更されたことを体験に知らせたいときに発火される。体験はその領域だけを描画することを選んでもよく、それは 性能に役立つ場合がある。

注: 体験はこのイベントを requestSession の promise 解決中に登録しなければならない。そうしないと、イベントが発火し、mask が体験から失われる可能性がある。

[SecureContext, Exposed=Window]
interface XRVisibilityMaskChangeEvent : Event {
  constructor(DOMString type, XRVisibilityMaskChangeEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
  readonly attribute XREye eye;
  readonly attribute unsigned long index;
  [SameObject] readonly attribute Float32Array vertices;
  [SameObject] readonly attribute Uint32Array indices;
};

dictionary XRVisibilityMaskChangeEventInit : EventInit {
  required XRSession session;
  required XREye eye;
  required unsigned long index;
  required Float32Array vertices;
  required Uint32Array indices;
};

session 属性は、そのイベントを 生成した XRSession を示す。

eye 属性は、mask がどの XREye に適用されるかを示す。

index 属性は、この mask が 適用される XRViewlist of views 内のオフセットを示す。

vertices 属性は、 X, Y 座標の list である。 体験は Z 座標が -1 であると仮定しなければならない。各 X, Y, Z 座標は頂点を記述する。この配列が空である場合、XRView の全領域が 描画されるべきである。

indices 属性は、vertices によって記述される頂点リストへのインデックスを記述する、indices の list である。 これらの indices は、描画されるべき eye の XRView の領域を 記述する。 この配列が空である場合、XRView の全領域が 描画されるべきである。

その領域は、eyeXRViewprojectionMatrix と、デフォルトの XRRigidTransform を使用して描画されなければならない。

注: これは、その領域が eye の現在の XRViewXRRigidTransform を使用してはならないことを意味する。

12.6. イベント種別

ユーザーエージェントは、次の新しいイベントを提供しなければならない。イベントの登録と発火は、DOM Events の通常の 振る舞いに従わなければならない。

ユーザーエージェントは、文書の origin が "xr-spatial-tracking" permissions policy の使用を許可されていない場合を除き、 immersive XR device の可用性が変更されたことを示すため、 XRSystem オブジェクト上で devicechange という名前のイベントを 発火しなければならない。

ユーザーエージェントは、XRSessionvisibility state が変更されるたびに、XRSessionEvent を使用して、XRSession 上で visibilitychange という名前のイベントを 発火しなければならない。

ユーザーエージェントは、アプリケーションまたはユーザーエージェントによってセッションが終了するとき、XRSessionEvent を使用して、XRSession 上で end という名前のイベントを 発火しなければならない。

ユーザーエージェントは、セッションの アクティブな XR 入力ソースのリストが変更されたとき、 XRInputSourcesChangeEvent を使用して、XRSession 上で inputsourceschange という名前のイベントを 発火しなければならない。

ユーザーエージェントは、セッションの アクティブな XR tracked sources のリストが変更されたとき、 XRInputSourcesChangeEvent を使用して、XRSession 上で trackedsourceschange という名前のイベントを 発火しなければならない。このイベントは、 tracked-sources がセッションの 許可済み機能の集合に含まれている場合にのみ発火されなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary action を 開始したとき、XRInputSourceEvent を使用して、XRSession 上で selectstart という名前のイベントを 発火しなければならない。 そのイベントは type . でなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary action を 終了したとき、または primary action を開始した XRInputSource が切断されたとき、XRInputSourceEvent を使用して、XRSession 上で selectend という名前のイベントを 発火しなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary action を完全に完了したとき、XRInputSourceEvent を使用して、XRSession 上で select という名前のイベントを 発火しなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary squeeze action を開始したとき、XRInputSourceEvent を使用して、XRSession 上で squeezestart という名前のイベントを 発火しなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary squeeze action を終了したとき、または primary squeeze action を開始した XRInputSource が切断されたとき、XRInputSourceEvent を使用して、XRSession 上で squeezeend という名前のイベントを 発火しなければならない。

ユーザーエージェントは、その XRInputSource の 1 つが primary squeeze action を完全に完了したとき、XRInputSourceEvent を使用して、XRSession 上で squeeze という名前のイベントを 発火しなければならない。

ユーザーエージェントは、XR CompositorXRSessioninternal nominal framerate を変更したとき、 XRSessionEvent を使用して、XRSession 上で frameratechange という名前のイベントを 発火しなければならない。

ユーザーエージェントは、XRSystem が、 ユーザーに表示される XRView の可視領域の変更を 通知したいとき、XRVisibilityMaskChangeEvent を使用して、XRSession 上で visibilitymaskchange という名前のイベントを 発火しなければならない。

ユーザーエージェントは、native origin または effective origin の 不連続、すなわちユーザー環境に対する origin の位置または向きに大きな変化が発生したとき、XRReferenceSpaceEvent を使用して、XRReferenceSpace 上で reset という名前のイベントを 発火しなければならない。 (例: ユーザーによる XR device の再較正の後、または XR device がトラッキングを失って回復した後に自動的に origin を移動する場合。)XRBoundedReferenceSpace について boundsGeometry が変更される場合にも、reset イベントが dispatch されなければならない。viewer のポーズが不連続を経験しても、XRReferenceSpace の origin の物理的マッピングが安定したままである場合、たとえば viewer が同じトラッキング領域内で一時的にトラッキングを失って回復する場合などには、 reset イベントは dispatch されてはならない。unbounded reference space が、重大な不連続が発生していない場合に、ユーザー付近の空間の安定性を維持するためにその native origin へ時間とともに小さな調整を行うときにも、reset イベントは dispatch されてはならない。そのイベントは、新しい origin を使用する任意の XR animation frame の実行前に dispatch されなければならない。reset イベントは、reset イベントを発火する reference space のすべての offset reference spaces 上でも dispatch されなければならず、 offset XRBoundedReferenceSpaceboundsGeometry も再計算されるべきである。

注: これは、セッションが reset リスナーを持つ任意の XRReferenceSpace への強い参照を保持する必要があることを意味する。

注: viewer の位置のジャンプは、アプリケーションが emulatedPosition 真偽値を監視することで処理できる。viewer の位置のジャンプが、emulatedPositiontrue から false に切り替わることと一致する場合、それは viewer がトラッキングを回復し、その新しい位置が以前のエミュレートされた 値からの補正を表すことを示す。物理的に移動せずに viewer が仮想世界内を移動できる "teleportation" メカニクスを持たない体験では、 これは一般にアプリケーションが望む振る舞いである。しかし、体験が "teleportation" メカニクスを提供する場合、 トラッキング回復後に viewer の位置を戻すようにジャンプさせることは、 不必要に不快である可能性がある。代わりに、そのようなアプリケーションがトラッキングを回復するときは、位置の突然の ジャンプを teleportation offset に吸収することで、仮想世界内の viewer の現在位置から単に体験を再開できる。これを行うために、開発者は getOffsetReferenceSpace() を呼び出して、前のフレーム以降に viewer の位置がジャンプした量だけ effective origin を調整した、置換用の reference space を 作成する。

13. セキュリティ、プライバシー、および快適性の考慮事項

WebXR Device API は強力な新機能を提供し、それに伴って、ユーザーエージェントが軽減するための手段を 講じなければならない、いくつかの固有のプライバシー、セキュリティ、および快適性のリスクをもたらす。

13.1. 機微情報

XR の文脈では、機微情報には、interpupillary distance (IPD) などの ユーザー設定可能なデータや、XRPose などの センサーベースのデータが含まれるが、これらに限定されない。すべての immersive sessions は、ユーザーのポーズが何かをレンダリングするために必要であるため、ある程度の機微データを公開する。 しかし、場合によっては、同じ機微情報が inline sessions を通じても公開される。

13.2. ユーザーの意図

あるアクションについての User intent は、そのアクションが意図的であり、ユーザーの同意を得ていることを示すユーザーからの信号である。

機微情報を公開する前、またはユーザーの体験に大きな影響を与えるアクションを許可する前に、user intent を確認することが必要になることが多い。この意図は、いくつかの方法で 伝達または観測されうる。

注: user intent を判断する一般的な方法は、通常は "enter VR" ボタンである UI コントロールの transient activation によるものである。activation は transient であるため、 XR セッションを要求する browsing context は、UI コントロールを含むコンテキストの ancestor、または same origin-domaindescendant でなければならず、かつ最近その browsing context の active document であった必要がある。

13.2.1. ユーザー activation

Transient activation は、一部のシナリオにおいて user intent の指標として機能してもよい。

13.2.2. Web アプリケーションの起動

一部の環境では、ページがアプリケーションとして提示され、没入型コンテンツを実行する明示的な意図をもってインストールされる場合がある。 その場合、web アプリケーションの起動も、user intent の指標として機能してもよい。

暗黙的な同意とは、 ユーザーエージェントが、明示的に尋ねることなく、ユーザーの同意について判断を下すことである。たとえば、 Web アプリケーションのインストール状態、訪問の頻度と新しさ、またはユーザーが没入型体験に入りたいという意図を 明確に示す、ユーザーエージェントが定義したアクションに基づく。XR データの機微性を考慮すると、暗黙的な信号に 依存する際には強い注意が推奨される。

明示的な同意とは、 ユーザーエージェントが、明示的に尋ねたことに基づいてユーザーの同意について判断を下すことである。明示的な同意を 収集する際、ユーザーエージェントは何が要求されているかの説明を提示し、ユーザーに拒否する選択肢を提供する。 ユーザー同意の要求は、保護されている機能とユーザーエージェントの選択に基づいて、多くの視覚的形式で提示できる。 Web アプリケーションのインストール状態は、インストール時に何らかの形式の 明示的な同意が要求される場合、明示的な同意の信号として 数えてもよい。

特定の origin について 明示的な同意が付与されたら、その同意は browsing context が終了するまで持続することが推奨される。ユーザーエージェントは、 user intent の暗黙的または明示的な信号に基づいて、この同意の持続時間を長くしたり短くしたり することを選択してもよいが、実装はこの推奨から逸脱するとき、特に暗黙的な信号に依存するときは注意を払うことが勧められる。 たとえば、没入型コンテンツを実行する明示的な意図でインストールされた Web アプリケーションでは、ユーザーの同意を 持続させることが適切な場合があるが、没入型コンテンツが副次的な機能であるインストール済み Web アプリケーションでは そうではない場合がある。

ユーザーエージェントがユーザーの同意をどれだけ長く持続させることを選択するかにかかわらず、 機微情報は、ended していない XRSession によってのみ公開されなければならない。

ユーザーエージェントに機能の使用について 明示的な同意を要求させる、複数の非 XR API がある。 ユーザーエージェントが active immersive session が 存在する間にユーザーの同意を要求する場合、ユーザーエージェントは同意要求をユーザーに表示する前に、 セッションをシャットダウンしなければならない。その機能に対する ユーザーの同意が active immersive session が 作成される前に付与されていた場合、セッションを終了する必要はない。

注: この制限は、ユーザーエージェントがセッション中の 明示的な同意を どのように管理すべきかについて合意に達するまで、すべてのユーザーエージェント間で振る舞いの同等性を確保するためのものである。 長期的な要件になることは想定されていない。

13.4. データ調整

場合によっては、throttling、quantizing、rounding、limiting、または XR device から報告されるデータをその他の方法で操作するなどの データ調整を通じて、セキュリティと プライバシーの脅威を軽減できる。これは、user intent が確立されている状況であっても、 fingerprinting を避けるために必要になることがある。しかし、データ調整による軽減策は、ユーザーの不快感をもたらさない 状況でのみ使用されなければならない。

13.4.1. Throttling

Throttling とは、機微情報が、 可能な場合より低い頻度で報告されることである。この軽減策は、サイトが user intent を推定したり、位置を推定したり、 ユーザープロファイリングを行ったりする能力を低減する可能性がある。しかし、適切に使用されない場合、throttling は ユーザーの不快感を引き起こす重大なリスクを伴う。さらに、多くの状況では、完全な軽減策を提供するには不十分な場合がある。

13.4.2. Rounding、quantization、および fuzzing

Rounding、quantization、および fuzzing は、本来であれば開発者に返される生データを変更する 3 種類の軽減策である。 Rounding は、それを表現するために使用される桁数を減らすことで、データの精度を下げる。 Quantization は、連続データを制約して、離散的な値の部分集合を報告するようにする。Fuzzing は、データにわずかなランダム誤差を 導入することである。総体として、これらの軽減策は fingerprinting を避けるために有用であり、そうしてもユーザーの 快適性に目立った影響を与えない場合に特に有用である。

13.4.3. Limiting

Limiting とは、データが特定の 範囲内にある場合にのみ報告されることである。たとえば、ユーザーが承認された場所から特定の距離を超えて移動したときに、 位置ポーズデータの報告を快適に制限することは可能である。この軽減策を採用するときは、ユーザー体験に悪影響がないことを 確実にするよう注意するべきである。範囲の終端での 'hard stop' は、混乱を招くユーザー体験を引き起こす可能性があるため、 避けることが望ましいことが多い。

13.5. 保護される機能

API によって公開される 機微情報は、 脅威プロファイルと、その脅威に対して必要な保護を共有するカテゴリに分けることができる。

13.5.1. 没入性

ユーザーは、immersive session が作成されるタイミングを制御できなければならない。なぜなら、その作成はユーザーの マシンに侵襲的な変更を引き起こすからである。たとえば、immersive session を開始すると、XR device のセンサーが作動し、デバイスのディスプレイへのアクセスを 引き継ぎ、XR ハードウェアへの別のアプリケーションのアクセスを終了させる可能性のある没入型コンテンツの提示を開始する。 また、一部のシステムでは大きな電力または性能上のオーバーヘッドが発生したり、ステータストレイまたはストアフロントの 起動を引き起こしたりすることがある。

与えられた global object について、immersive session request is allowed かどうかを判断するには、 ユーザーエージェントは次の手順を実行しなければならない:

  1. 要求が、global objecttransient activation を持っている間、または web application を起動しているときに行われたのでない場合、false を返す

  2. immersive session を開始するための user intent が、 明示的な同意 または 暗黙的な同意のいずれかによって十分に理解されていない場合、 false を返す

  3. true を返す

inline session の開始は、 immersive session の開始と同じ要件を暗黙的に 伴うものではないが、セッションの requested features に応じて追加の要件が課される場合がある。

与えられた global object について、inline session request is allowed かどうかを判断するには、 ユーザーエージェントは次の手順を実行しなければならない:

  1. セッション要求が、inline-stereo 以外の任意の required features または optional features を含んでいた場合は requiresUserIntenttrue とし、そうでなければ false とする。

  2. requiresUserIntenttrue であり、要求が global objecttransient activation を持っている間、または web application を起動しているときに行われたのでない場合、false を返す。

  3. global objectWindow でない場合、false を返す。

  4. true を返す。

13.5.2. ポーズ

センサーデータに基づく場合、XRPose および XRViewerPose は、input sniffing、gaze tracking、または fingerprinting を含む多くの方法で悪用されうる 機微情報を公開する。

XRSession sessionposes may be reported かどうかを判断するには、ユーザーエージェントは 次の手順を実行しなければならない:

  1. sessionrelevant global objectcurrent global object でない場合、false を返す。

  2. sessionvisibilityState"hidden" である場合、false を返す。

  3. ポーズデータを次のように返せるかどうかを判断する:

    ポーズデータが fingerprintable なセンサーデータを公開しないことをユーザーエージェントが知っている場合

    true を返す。

    fingerprinting または profiling を防止するため、基礎となるセンサーデータに データ調整が適用される場合

    true を返す。

    user intent が、明示的な同意または 暗黙的な同意 のいずれかによって十分に理解されている場合

    true を返す。

    そうでない場合

    false を返す。

注: ユーザーエージェントが poses が fingerprintable なデータを公開しないと判断する方法は、ユーザーエージェントの裁量に委ねられる。

XRViewerPoseXRPose の 主な違いは、XRView 情報が 含まれることである。複数の view が存在し、これらの view 間の物理的関係がユーザーによって設定可能である場合、 これらの view 間の関係は、ユーザーの fingerprinting または profiling に使用できるため、機微情報とみなされる。

XRView 間の関係が XR device を一意に識別しうる場合、 ユーザーエージェントは fingerprinting を防止するために、XRView データを 匿名化しなければならない。匿名化の方法はユーザーエージェントの裁量に委ねられる。

注: さらに、XRView 間の関係が、 ユーザー設定の interpupillary distance (IPD) によって影響される場合、ユーザーエージェントは、 いかなる XRView データを 報告する前に、セッション作成中に 明示的な同意を 要求することが強く推奨される。

13.5.3. Reference spaces

使用される reference spaces に応じて、いくつかの異なる種類の 機微情報がアプリケーションに公開される場合がある。

その結果、公開される 機微情報が 安全に扱われることを保証するため、さまざまな reference space 型には作成に制限が課される:

ほとんどの reference spaces は、その reference space を使用するための user intent が、明示的な同意または 暗黙的な同意のいずれかによって 十分に理解されていることを要求する。詳細は feature requirements 表を参照。

相互に関連付けられる能力を持つ、"local", "local-floor", および "bounded-floor" reference spaces の任意のグループは、共通の native origin を共有しなければならない。この制限は、"unbounded" reference spaces の作成が制限されている場合にのみ適用される。

2 つの空間、spacebaseSpace の間で poses must be limited かどうかを判断するには、ユーザーエージェントは 次の手順を実行しなければならない:

  1. space または baseSpace のいずれかが XRBoundedReferenceSpace であり、もう一方の空間の native origin が、ユーザーエージェントによって判断される 妥当な距離よりもさらに native bounds geometry の外側に ある場合、true を返す。

  2. space または baseSpace のいずれかが、XRReferenceSpace であり、type"local" または "local-floor" であり、その空間どうしの native origins の間の距離が、ユーザーエージェントによって 判断される妥当な距離より大きい場合、true を返す。

  3. false を返す。

注: 文書可視性の要件は [DEVICE-ORIENTATION] に基づく。

注: "local" または "local-floor" reference space に対して相対的に報告される poses は、XRReferenceSpacenative origin から 15 メートルの距離に 制限されることが 提案される。

注: XRBoundedReferenceSpace に対して相対的に報告される poses は、XRBoundedReferenceSpacenative bounds geometry の外側 1 メートルの 距離に 制限されることが提案される。

13.6. 信頼された環境

Trusted UI は、ユーザーエージェントによって 提示され、ユーザーが操作できるがページは操作できないインターフェイスである。ユーザーエージェントは trusted UI の表示をサポートしなければならない。

trusted UI は、次の特性を持たなければならない:

大まかに言えば、trusted UI をサポートしたいユーザーエージェントには 2 つの選択肢がある。 1 つの選択肢は trusted immersive UI であり、これは immersive mode を終了しない trusted UI である。trusted immersive UI の実装は困難な場合がある。なぜなら XRWebGLLayer バッファは XR Device ディスプレイを満たし、ユーザーエージェントは通常、自身の使用のために ピクセルを "reserve" しないからである。ユーザーエージェントは trusted immersive UI をサポートすることを 要求されない。代わりに immersive mode を一時停止/終了し、非 immersive な trusted UI をユーザーに表示してもよい。

注: trusted UI の例には次が含まれる:

ポーズおよび入力情報を読み取る能力は、trusted UI の完全性に対するリスクをもたらす。ページがこの情報を使用して、 ユーザーが trusted UI と操作している間に行った選択を覗き見し、キーボード入力を推測することを 含めて行える可能性があるためである。このリスクを防止するため、ユーザーが URL バーまたはシステムダイアログなどの trusted UIimmersive または非 immersive)と操作しているとき、ユーザーエージェントは すべての XRSessionvisibility state"hidden" または "visible-blurred" に設定しなければならない。加えて、悪意のあるページが他のページ上の入力を監視できることを防止するため、ユーザーエージェントは、 currently focused areaXRSession を 作成した文書に属さない場合、XRSessionvisibility state"hidden" に設定しなければならない。

trusted UI の特定のインスタンスについて "hidden" または "visible-blurred" のどちらを使用するかを選ぶとき、ユーザーエージェントはポーズ情報がセキュリティリスクであるかどうかを考慮しなければならない。 たとえば、テキスト入力、とくにパスワード入力を含む trusted UI は、ユーザーが入力しているときの 動きを通じて、入力されたテキストを漏えいさせる可能性がある。そのような場合、ユーザーエージェントは eye tracking 関連の いかなる情報の公開も停止すべきである。

ユーザーエージェントは、permissions prompts を表示するために trusted UI を使用しなければならない。

仮想環境がユーザーの視点を低遅延かつ高フレームレートで一貫して更新しない場合、ユーザーは方向感覚を失ったり、 身体的に気分が悪くなったりする可能性がある。ページに一貫して高性能で正しいコンテンツを生成させることは不可能であるため、 ユーザーエージェントは、ページコンテンツから非同期に実行される、トラッキングされた信頼された環境と XR Compositor を提供しなければならない。compositor は、trusted content と untrusted content を合成する責任を負う。 コンテンツの性能が不十分である、フレームを送信しない、または予期せず終了する場合でも、ユーザーエージェントは 応答性のある trusted UI を提示し続けられるべきである。

さらに、ページコンテンツは、性能とは関係のない方法でユーザーを不快にする能力を持つ。不適切に適用されたトラッキング、 点滅する色、および不快にさせる、怖がらせる、または威圧することを意図したコンテンツは、ユーザーが XR 体験から すばやく退出したいと思う原因となりうるコンテンツの例である。このような場合に XR device を取り外すことは、 常に迅速または実用的な選択肢であるとは限らない。これに対応するため、ユーザーエージェントは、予約された ハードウェアボタンを押す、またはジェスチャーを行うなど、WebXR コンテンツから抜け出してユーザーエージェントの trusted UI を表示するアクションをユーザーに提供しなければならない。

13.7. コンテキスト分離

trusted UI は、ページによって使用される任意のレンダリングコンテキスト(たとえば任意の WebGL レンダリングコンテキスト)から 状態が分離された、独立したレンダリングコンテキストによって描画されなければならない。これは、ページが trusted UI の コンテキストの状態を破壊し、それによってトラッキングされた環境を適切にレンダリングできなくなることを防止するためである。 また、ページが trusted UI から画像をキャプチャできる可能性も防ぎ、それによってプライベートな情報の漏えいを防止する。

また、CORS 関連の脆弱性を防止するため、各 browsing context は、XRSession など、 API によって返されるオブジェクトの新しいインスタンスを見ることになる。ある relevant realm を持つ XRWebGLLayer 上に設定された context などの属性は、same origin を持たない relevant realm を持つ XRWebGLLayer を通じて読み取ることができるべきではない。同様に、API 上で呼び出されるメソッドは、他の browsing contexts 上で観測可能な状態変化を引き起こしてはならない。 例: システムレベルの orientation reset を可能にするメソッドは公開されない。これは、悪意のあるページによって繰り返し 呼び出され、他のページが適切にトラッキングすることを妨げる可能性があるためである。ただし、ユーザーエージェントは、 ユーザージェスチャーまたはシステムメニューによって引き起こされるシステムレベルの orientation reset を尊重しなければならない。

注: これは、1 つの browsing context が immersive mode に入り、デバイスのロックを取得し、 ほかの browsing contexts 上で devicechange イベントを発火する可能性があることによって引き起こされる状態変化には適用されない。

13.8. Fingerprinting

API がユーザーに利用可能なハードウェアとその能力を記述することを考えると、これは必然的に fingerprinting のための 追加の表面を提供する。これを完全に避けることは不可能であるが、ユーザーエージェントは問題を軽減するための手段を講じるべきである。 この仕様は、利用可能なハードウェアの報告を一度に 1 つのデバイスだけに制限する。これにより、複数のヘッドセットが接続されている まれなケースを fingerprinting の信号として使用することを防ぐ。また、報告されるデバイスには文字列識別子がなく、 XRSession が作成されるまでデバイスの能力に関する情報をほとんど公開しない。XRSession の作成時には、機微情報が公開される場合に追加の保護が必要になる。

13.8.1. isSessionSupported() の fingerprinting に関する考慮事項

isSessionSupported() は user activation なしで呼び出すことができるため、fingerprinting vector として使用される可能性がある。

"xr-session-supported" powerful feature は、isSessionSupported() API へのアクセスをゲートする。

"xr-session-supported" の permission 関連の アルゴリズムと型は、次のように定義される:

permission descriptor type
dictionary XRSessionSupportedPermissionDescriptor: PermissionDescriptor {
  XRSessionMode mode;
};

name for XRPermissionDescriptor"xr-session-supported" である。

13.8.2. "xr-session-supported" を自動的に付与するタイミングに関する考慮事項

Web 上では、プライバシーとパーソナライゼーションの間に緊張関係があることが多い。この節は、そのトレードオフを どこで限定できるか、またユーザーエージェントがプライバシーを損なうことなく、ブラウザーの WebXR 能力を isSessionSupported() を通じてサイトに説明できるのはいつかについての指針を提供する。

"xr-session-supported" は、以下の基準に基づき、 一部のシステムでは自動的に付与されてもよい。これはより良いユーザー体験を提供し、permissions fatigue を軽減できる。

ユーザーエージェントの集合は、すべてが同じ userAgent および appVersion を報告する場合、ユーザーエージェント文字列によって区別不能である。 そのようなクラスは通常、実行されているブラウザーバージョンとプラットフォーム/デバイスによって識別されるが、 接続されている外部デバイスの状態によって区別することはできない。ユーザーエージェント文字列によって区別不能な ユーザーエージェントという概念を使用して、fingerprinting リスクを適切に評価できる。

ユーザーエージェント文字列によって区別不能な一部の ユーザーエージェントは、与えられた XRSessionMode のセッションを 決してサポートしない例: mobile AR サポートの要件を満たさないことが分かっている電話機種上で実行される ユーザーエージェント。 これらの場合、isSessionSupported() が常にその XRSessionMode はサポートされないと報告することには、fingerprinting リスクはほとんどない。なぜなら、そのようなデバイスはすべて 一貫して同じ値を報告し、デバイス種別とモデルは userAgent など他の方法で推定できると仮定されるためである。したがって、そのようなシステムでは、ユーザーエージェントは関連する XRSessionMode について "xr-session-supported" を自動的に拒否すべきである。

ユーザーエージェント文字列によって区別不能な他の ユーザーエージェントは、与えられた XRSessionMode のセッションを 通常サポートする例: VR ヘッドセット内でのみ実行される、WebXR をサポートすることが知られている ユーザーエージェントは、ユーザーによって特にブロックされていない限り、"immersive-vr" セッションをサポートする可能性が高い。 これらの場合、正確ではあるが、その XRSessionMode はサポートされないと報告することは、ユーザーについてより一意に識別できる情報を提供することになる。そのため、 その XRSessionMode が常に利用可能であると報告し、requestSession() が失敗することを許す方が、プライバシー保護の観点では望ましく、ユーザーに混乱を生じさせる原因にもなりにくい。 そのようなシステムでは、ユーザーエージェントは関連する XRSessionMode について "xr-session-supported" を自動的に付与すべきである。

XR 周辺機器をサポートするデスクトップシステムなど、XR 能力の可用性が非常に変動しやすい ユーザーエージェント文字列によって区別不能な ユーザーエージェントは、最も高い fingerprinting リスクを提示する。そのようなデバイス上のユーザーエージェントは、 isSessionSupported() API が追加の fingerprinting bits を提供できるような方法で、"xr-session-supported" を自動的に付与すべきではない。

注: そのような場合を処理するための許容可能なアプローチの例は次のとおりである:
  • isSessionSupported() が呼び出されたときに、"xr-session-supported" について常に 明示的な同意を判断する (キャッシュされた permissions prompt などを伴う可能性がある)。

  • "xr-session-supported" を自動的に付与するが、 適切なハードウェアまたはソフトウェアが存在するかどうかにかかわらず、XR 能力が一貫して利用可能でない プラットフォーム上であっても isSessionSupported() が常に true を報告するようにする。これはユーザーの使いやすさを犠牲にする。なぜなら、 表示できないユーザーに対してページが XR コンテンツを宣伝する原因になるためである。

  • 適切なハードウェアが存在する場合は、isSessionSupported()"xr-session-supported" について 明示的な同意を要求させ、そのようなハードウェアが存在しない場合は、 適切にランダムな長さの時間の後に false を返す。そのような実装では、コンテンツが、 ユーザーエージェントが XR ハードウェアに接続されていなかった場合と、XR ハードウェアに接続されていたが ユーザーが 明示的な同意の提供を拒否した場合とを区別できてはならない。

選択された技法が何であれ、明示的な同意なしに 接続された XR ハードウェアに関する追加の知識を明らかにすべきではない。

14. 統合

14.1. Permissions Policy

この仕様は、spatial tracking の使用を必要とする任意の XRSessionrequestSession() によって返されてもよいかどうか、および spatial tracking を必要とする session modes のサポートが、isSessionSupported() または navigator.xr オブジェクト上の devicechange イベントのいずれかによって示されてもよいかどうかを 制御する policy-controlled feature を定義する。

この機能の feature identifier は "xr-spatial-tracking" である。

この機能の default allowlist["self"] である。

注: 文書の origin"xr-spatial-tracking" permissions policy の使用を許可されていない場合、 すべての immersive sessions はブロックされる。 なぜなら、すべての immersive sessions は spatial tracking の何らかの使用を必要とするからである。"inline" セッションは引き続き許可されるが、"viewer" XRReferenceSpace のみを使用するよう制限される。

14.2. Permissions API 統合

[permissions] API は、 Web サイトがユーザーに permissions を要求し、どの permissions が付与されているかを照会するための統一的な方法を提供する。

"xr" powerful feature の permission 関連アルゴリズムと型は 次のように定義される:

permission descriptor type
dictionary XRPermissionDescriptor: PermissionDescriptor {
  XRSessionMode mode;
  sequence<DOMString> requiredFeatures;
  sequence<DOMString> optionalFeatures;
};

name for XRPermissionDescriptor"xr" である。

permission result type
[Exposed=Window]
interface XRPermissionStatus: PermissionStatus {
  attribute FrozenArray<DOMString> granted;
};
permission query algorithm
XRPermissionDescriptor descriptorXRPermissionStatus status を用いて "xr" permission を照会するには、UA は次の手順を実行しなければならない:
  1. statusstate を、descriptorpermission state に設定する。

  2. statusstate"denied" である場合、statusgranted を空の FrozenArray に設定し、これらの手順を中止する。

  3. result を、descriptorrequiredFeatures, optionalFeatures, および mode を与えて requested features を解決する結果とする。

  4. resultnull である場合、次の手順を実行する:

    1. statusgranted を空の FrozenArray に設定する。

    2. statusstate"denied" に設定する。

    3. これらの手順を中止する。

  5. (consentRequired, consentOptional, granted) を result のフィールドとする。

  6. statusgrantedgranted に設定する。

  7. consentRequired空で、 かつ consentOptional空である場合、 statusstate"granted" に設定し、これらの手順を中止する

  8. statusstate"prompt" に設定する。

permission request algorithm
XRPermissionDescriptor descriptorXRPermissionStatus status を用いて "xr" permission を要求するには、UA は次の手順を実行しなければならない:
  1. statusgranted を空の FrozenArray に設定する。

  2. requiredFeaturesdescriptorrequiredFeatures とする。

  3. optionalFeaturesdescriptoroptionalFeatures とする。

  4. device を、mode, requiredFeatures, および optionalFeatures について current device を取得する結果とする。

  5. result を、requiredFeatures,optionalFeatures, および mode を与えて requested features を解決する結果とする。

  6. resultnull である場合、次の手順を実行する:

    1. statusstate"denied" に設定する。

    2. これらの手順を中止する。

  7. (consentRequired, consentOptional, granted) を result のフィールドとする。

  8. ユーザーエージェントはこの時点で、呼び出し元アルゴリズムが consentRequired および consentOptional 内の任意の機能を使用するための ユーザーの permission を尋ねてもよい。これらの prompt の結果は、これらの機能を有効化するための user intent の明確な信号があるかどうかを判断するときに含めるべきである。

  9. consentRequired 内の各 feature について、次の手順を実行する:

    1. ユーザーエージェントはこの時点で、呼び出し元アルゴリズムが feature を使用するためのユーザーの permission を尋ねてもよい。これらの prompt の結果は、 feature を有効化するための user intent の明確な信号が あるかどうかを判断するときに含めるべきである。

    2. feature を有効化するための user intent の明確な信号が判断されていない場合、 次の手順を実行する:

      1. statusstate"denied" に設定し、これらの手順を中止する。

    3. featuregranted 内にない場合、featuregranted に追加する。

  10. consentOptional 内の各 feature について、次の手順を実行する:

    1. ユーザーエージェントはこの時点で、呼び出し元アルゴリズムが feature を使用するためのユーザーの permission を尋ねてもよい。これらの prompt の結果は、 feature を有効化するための user intent の明確な信号が あるかどうかを判断するときに含めるべきである。

    2. feature を有効化するための user intent の明確な信号が判断されていない場合、 次の entry に進む。

    3. featuregranted 内にない場合、featuregranted に追加する。

  11. statusgrantedgranted に設定する。

  12. granted のすべての要素を、mode について deviceset of granted features に 追加する。

  13. statusstate"granted" に設定する。

注: ユーザーエージェントには、 user intent の 明確な信号があるかどうかを測るとき、要求されたすべての機能について permissions prompts をまとめる自由があるが、 1 つずつ表示することも許される。

注: Web アプリケーションについて user intent を判断するとき、 ユーザーエージェントは、それが Web アプリケーションとしてユーザーによって明示的に 起動されたことを 確認しなければならない。インストール済み Web アプリケーションの origin と一致するかどうかだけを確認してはならない。

XRSessionMode mode について、requiredFeatures および optionalFeatures が与えられたとき、 requested features を解決するには、ユーザーエージェントは次の手順を実行しなければならない:

  1. consentRequired を、DOMString の空の list とする。

  2. consentOptional を、DOMString の空の list とする。

  3. granted を、DOMString の空の list とする。

  4. device を、mode, requiredFeatures, および optionalFeatures について current device を取得する結果とする。

  5. previouslyEnabled を、mode について deviceset of granted features とする。

  6. devicenull であるか、devicelist of supported modesmode含まない 場合、次の手順を実行する:

    1. tuple (consentRequired, consentOptional, granted) を返す

  7. mode に関連付けられた default features 表内の すべての feature descriptor を、まだ存在しない場合は granted に追加する。

  8. requiredFeatures 内の各 feature について、次の手順を実行する:

    1. featurenull である場合、次の entry に 進む

    2. feature が有効な feature descriptor でない場合、 null を返す。

    3. feature がすでに granted 内にある場合、次の entry に進む。

    4. 要求元文書の origin が、feature requirements 表で示されるように、 feature によって必要とされる任意の permissions policy の使用を許可されていない場合、 null を返す。

    5. sessionXR device が、feature によって 記述される機能を サポート可能 でない、またはユーザーエージェントがそれ以外の理由でその機能を拒否すると判断した場合、 null を返す。

    6. feature によって記述される機能が 明示的な同意を必要とし、 featurepreviouslyEnabled 内にない場合、それを consentRequired に追加する。

    7. そうでなければ、featuregranted に追加する。

  9. optionalFeatures 内の各 feature について、次の手順を実行する:

    1. featurenull である場合、次の entry に 進む

    2. feature が有効な feature descriptor でない場合、次の entry に 進む

    3. feature がすでに granted 内にある場合、次の entry に進む。

    4. 要求元文書の origin が、feature requirements 表で示されるように、 feature によって必要とされる任意の permissions policy の使用を許可されていない場合、 次の entry に進む。

    5. sessionXR device が、feature によって 記述される機能を サポート可能 でない、またはユーザーエージェントがそれ以外の理由でその機能を拒否すると判断した場合、 次の entry に進む。

    6. feature によって記述される機能が 明示的な同意を必要とし、 featurepreviouslyEnabled 内にない場合、それを consentOptional に追加する。

    7. そうでなければ、featuregranted に追加する。

  10. tuple (|consentRequired|, |consentOptional|, |granted|) を返す

変更点

Candidate Recommendation Snapshot, 2022年3月31日 からの変更点

Working Draft 2020年7月24日 からの変更点

Working Draft 2019年10月10日 からの変更点

新機能:

変更点:

First Public Working Draft 2019年2月5日 からの変更点

新機能:

削除された機能:

変更点:

15. 謝辞

WebXR Device API 仕様への貢献について、以下の個人に感謝する:

そして、この冒険全体のきっかけを作ってくれた Vladimir Vukicevic (Unity) に特別な感謝を捧げる!

適合性

文書の 慣例

適合性要件は、記述的な表明と RFC 2119 の用語を組み合わせて表現される。 この文書の規範的部分における “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, および “OPTIONAL” というキーワードは、RFC 2119 で説明されるように解釈されるべきである。 ただし、読みやすさのため、 この仕様ではこれらの語がすべて大文字で現れるとは限らない。

この仕様のすべてのテキストは、 非規範として明示的に印付けられた節、例、および注を除き、規範的である。 [RFC2119]

この仕様の例は “for example” という語で導入されるか、 または次のように class="example" によって規範的テキストから 分離される:

これは参考情報としての例の一例である。

参考情報としての注は “Note” という語で始まり、 次のように class="note" によって規範的テキストから 分離される:

注: これは参考情報としての注である。

適合する アルゴリズム

アルゴリズムの一部として命令形で述べられる要件 (たとえば "strip any leading space characters" または "return false and abort these steps" など)は、 そのアルゴリズムを導入する際に用いられたキーワード ("must", "should", "may" など)の意味で解釈されるべきである。

アルゴリズムまたは特定の手順として述べられる適合性要件は、 最終結果が等価である限り、 任意の方法で実装できる。 とくに、この仕様で定義されるアルゴリズムは理解しやすいことを意図しており、 高性能であることを意図していない。 実装者には最適化が推奨される。

索引

この仕様で定義される用語

参照により定義される用語

参考文献

規範的参考文献

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. 4 December 2025. CRD. URL: https://www.w3.org/TR/geometry-1/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. 24 March 2026. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PERMISSIONS]
Marcos Caceres; Mike Taylor. Permissions. 6 October 2025. WD. URL: https://www.w3.org/TR/permissions/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy. 6 October 2025. WD. URL: https://www.w3.org/TR/permissions-policy-1/
[POINTEREVENTS4]
Patrick Lauke; Robert Flack. Pointer Events. 22 May 2026. WD. URL: https://www.w3.org/TR/pointerevents4/
[POINTERLOCK]
Mustaq Ahmed; Vincent Scheib. Pointer Lock 2.0. 25 February 2026. WD. URL: https://www.w3.org/TR/pointerlock-2/
[REQUESTIDLECALLBACK]
Scott Haseley. requestIdleCallback(). 21 May 2025. WD. URL: https://www.w3.org/TR/requestidlecallback/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBGL-2]
Dean Jackson; Jeff Gilbert. WebGL 2.0 Specification. 12 August 2017. URL: https://www.khronos.org/registry/webgl/specs/latest/2.0/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXRLAYERS-1]
Rik Cabanier. WebXR Layers API Level 1. 22 January 2026. WD. URL: https://www.w3.org/TR/webxrlayers-1/

非規範的参考文献

[DEVICE-ORIENTATION]
Reilly Grant; Marcos Caceres. Device Orientation and Motion. 12 February 2025. CRD. URL: https://www.w3.org/TR/orientation-event/
[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR Augmented Reality Module - Level 1. 25 April 2025. CRD. URL: https://www.w3.org/TR/webxr-ar-module-1/

IDL 索引

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute XRSystem xr;
};

[SecureContext, Exposed=Window] interface XRSystem : EventTarget {
  // Methods
  Promise<boolean> isSessionSupported(XRSessionMode mode);
  [NewObject] Promise<XRSession> requestSession(XRSessionMode mode, optional XRSessionInit options = {});

  // Events
  attribute EventHandler ondevicechange;
};

enum XRSessionMode {
  "inline",
  "immersive-vr",
  "immersive-ar"
};

dictionary XRSessionInit {
  sequence<DOMString> requiredFeatures;
  sequence<DOMString> optionalFeatures;
};

enum XRVisibilityState {
  "visible",
  "visible-blurred",
  "hidden",
};

[SecureContext, Exposed=Window] interface XRSession : EventTarget {
  // Attributes
  readonly attribute XRVisibilityState visibilityState;
  readonly attribute float? frameRate;
  readonly attribute Float32Array? supportedFrameRates;
  [SameObject] readonly attribute XRRenderState renderState;
  [SameObject] readonly attribute XRInputSourceArray inputSources;
  [SameObject] readonly attribute XRInputSourceArray trackedSources;
  readonly attribute FrozenArray<DOMString> enabledFeatures;
  readonly attribute boolean isSystemKeyboardSupported;

  // Methods
  undefined updateRenderState(optional XRRenderStateInit state = {});
  Promise<undefined> updateTargetFrameRate(float rate);
  [NewObject] Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type);

  unsigned long requestAnimationFrame(XRFrameRequestCallback callback);
  undefined cancelAnimationFrame(unsigned long handle);

  Promise<undefined> end();

  // Events
  attribute EventHandler onend;
  attribute EventHandler oninputsourceschange;
  attribute EventHandler onselect;
  attribute EventHandler onselectstart;
  attribute EventHandler onselectend;
  attribute EventHandler onsqueeze;
  attribute EventHandler onsqueezestart;
  attribute EventHandler onsqueezeend;
  attribute EventHandler onvisibilitychange;
  attribute EventHandler onframeratechange;
};

dictionary XRRenderStateInit {
  double depthNear;
  double depthFar;
  boolean passthroughFullyObscured;
  double inlineVerticalFieldOfView;
  XRWebGLLayer? baseLayer;
  sequence<XRLayer>? layers;
};

[SecureContext, Exposed=Window] interface XRRenderState {
  readonly attribute double depthNear;
  readonly attribute double depthFar;
  readonly attribute boolean? passthroughFullyObscured;
  readonly attribute double? inlineVerticalFieldOfView;
  readonly attribute XRWebGLLayer? baseLayer;
};

callback XRFrameRequestCallback = undefined (DOMHighResTimeStamp time, XRFrame frame);

[SecureContext, Exposed=Window] interface XRFrame {
  [SameObject] readonly attribute XRSession session;
  readonly attribute DOMHighResTimeStamp predictedDisplayTime;

  XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace);
  XRPose? getPose(XRSpace space, XRSpace baseSpace);
};

[SecureContext, Exposed=Window] interface XRSpace : EventTarget {

};

enum XRReferenceSpaceType {
  "viewer",
  "local",
  "local-floor",
  "bounded-floor",
  "unbounded"
};

[SecureContext, Exposed=Window]
interface XRReferenceSpace : XRSpace {
  [NewObject] XRReferenceSpace getOffsetReferenceSpace(XRRigidTransform originOffset);

  attribute EventHandler onreset;
};

[SecureContext, Exposed=Window]
interface XRBoundedReferenceSpace : XRReferenceSpace {
  readonly attribute FrozenArray<DOMPointReadOnly> boundsGeometry;
};

[SecureContext, Exposed=Window] interface mixin XRViewGeometry {
  readonly attribute Float32Array projectionMatrix;
  [SameObject] readonly attribute XRRigidTransform transform;
};

enum XREye {
  "none",
  "left",
  "right"
};

[SecureContext, Exposed=Window] interface XRView {
  readonly attribute XREye eye;
  readonly attribute unsigned long index;
  readonly attribute double? recommendedViewportScale;

  undefined requestViewportScale(double? scale);
};

XRView includes XRViewGeometry;

[SecureContext, Exposed=Window] interface XRViewport {
  readonly attribute long x;
  readonly attribute long y;
  readonly attribute long width;
  readonly attribute long height;
};

[SecureContext, Exposed=Window]
interface XRRigidTransform {
  constructor(optional DOMPointInit position = {}, optional DOMPointInit orientation = {});
  [SameObject] readonly attribute DOMPointReadOnly position;
  [SameObject] readonly attribute DOMPointReadOnly orientation;
  readonly attribute Float32Array matrix;
  [SameObject] readonly attribute XRRigidTransform inverse;
};

[SecureContext, Exposed=Window] interface XRPose {
  [SameObject] readonly attribute XRRigidTransform transform;
  [SameObject] readonly attribute DOMPointReadOnly? linearVelocity;
  [SameObject] readonly attribute DOMPointReadOnly? angularVelocity;

  readonly attribute boolean emulatedPosition;
};

[SecureContext, Exposed=Window] interface XRViewerPose : XRPose {
  [SameObject] readonly attribute FrozenArray<XRView> views;
};

enum XRHandedness {
  "none",
  "left",
  "right"
};

enum XRTargetRayMode {
  "gaze",
  "tracked-pointer",
  "screen",
  "transient-pointer"
};

[SecureContext, Exposed=Window]
interface XRInputSource {
  readonly attribute XRHandedness handedness;
  readonly attribute XRTargetRayMode targetRayMode;
  [SameObject] readonly attribute XRSpace targetRaySpace;
  [SameObject] readonly attribute XRSpace? gripSpace;
  [SameObject] readonly attribute FrozenArray<DOMString> profiles;
  readonly attribute boolean skipRendering;
};

[SecureContext, Exposed=Window]
interface XRInputSourceArray {
  iterable<XRInputSource>;
  readonly attribute unsigned long length;
  getter XRInputSource(unsigned long index);
};

[SecureContext, Exposed=Window]
interface XRLayer : EventTarget {};


typedef (WebGLRenderingContext or
         WebGL2RenderingContext) XRWebGLRenderingContext;

dictionary XRWebGLLayerInit {
  boolean antialias = true;
  boolean depth = true;
  boolean stencil = false;
  boolean alpha = true;
  boolean ignoreDepthValues = false;
  double framebufferScaleFactor = 1.0;
};

[SecureContext, Exposed=Window]
interface XRWebGLLayer: XRLayer {
  constructor(XRSession session,
             XRWebGLRenderingContext context,
             optional XRWebGLLayerInit layerInit = {});
  // Attributes
  readonly attribute boolean antialias;
  readonly attribute boolean ignoreDepthValues;
  attribute float? fixedFoveation;

  [SameObject] readonly attribute WebGLFramebuffer? framebuffer;
  readonly attribute unsigned long framebufferWidth;
  readonly attribute unsigned long framebufferHeight;

  // Methods
  XRViewport? getViewport(XRView view);

  // Static Methods
  static double getNativeFramebufferScaleFactor(XRSession session);
};

partial dictionary WebGLContextAttributes {
    boolean xrCompatible = false;
};

partial interface mixin WebGLRenderingContextBase {
    [NewObject] Promise<undefined> makeXRCompatible();
};

[SecureContext, Exposed=Window]
interface XRSessionEvent : Event {
  constructor(DOMString type, XRSessionEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
};

dictionary XRSessionEventInit : EventInit {
  required XRSession session;
};

[SecureContext, Exposed=Window]
interface XRInputSourceEvent : Event {
  constructor(DOMString type, XRInputSourceEventInit eventInitDict);
  [SameObject] readonly attribute XRFrame frame;
  [SameObject] readonly attribute XRInputSource inputSource;
};

dictionary XRInputSourceEventInit : EventInit {
  required XRFrame frame;
  required XRInputSource inputSource;
};

[SecureContext, Exposed=Window]
interface XRInputSourcesChangeEvent : Event {
  constructor(DOMString type, XRInputSourcesChangeEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
  [SameObject] readonly attribute FrozenArray<XRInputSource> added;
  [SameObject] readonly attribute FrozenArray<XRInputSource> removed;
};

dictionary XRInputSourcesChangeEventInit : EventInit {
  required XRSession session;
  required sequence<XRInputSource> added;
  required sequence<XRInputSource> removed;

};

[SecureContext, Exposed=Window]
interface XRReferenceSpaceEvent : Event {
  constructor(DOMString type, XRReferenceSpaceEventInit eventInitDict);
  [SameObject] readonly attribute XRReferenceSpace referenceSpace;
  [SameObject] readonly attribute XRRigidTransform? transform;
};

dictionary XRReferenceSpaceEventInit : EventInit {
  required XRReferenceSpace referenceSpace;
  XRRigidTransform? transform = null;
};

[SecureContext, Exposed=Window]
interface XRVisibilityMaskChangeEvent : Event {
  constructor(DOMString type, XRVisibilityMaskChangeEventInit eventInitDict);
  [SameObject] readonly attribute XRSession session;
  readonly attribute XREye eye;
  readonly attribute unsigned long index;
  [SameObject] readonly attribute Float32Array vertices;
  [SameObject] readonly attribute Uint32Array indices;
};

dictionary XRVisibilityMaskChangeEventInit : EventInit {
  required XRSession session;
  required XREye eye;
  required unsigned long index;
  required Float32Array vertices;
  required Uint32Array indices;
};

dictionary XRSessionSupportedPermissionDescriptor: PermissionDescriptor {
  XRSessionMode mode;
};

dictionary XRPermissionDescriptor: PermissionDescriptor {
  XRSessionMode mode;
  sequence<DOMString> requiredFeatures;
  sequence<DOMString> optionalFeatures;
};

[Exposed=Window]
interface XRPermissionStatus: PermissionStatus {
  attribute FrozenArray<DOMString> granted;
};

MDN

Navigator/xr

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

WebGLRenderingContext/makeXRCompatible

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?

WebGLRenderingContext/makeXRCompatible

In only one current engine.

FirefoxNoneSafariNoneChrome79+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera MobileNone
MDN

XRBoundedReferenceSpace/boundsGeometry

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRBoundedReferenceSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRFrame/getPose

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRFrame/getViewerPose

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRFrame/session

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRFrame

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource/gripSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource/handedness

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource/profiles

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource/targetRayMode

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource/targetRaySpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSource

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceArray/length

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceArray

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceEvent/XRInputSourceEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceEvent/frame

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceEvent/inputSource

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourceEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourcesChangeEvent/XRInputSourcesChangeEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourcesChangeEvent/added

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourcesChangeEvent/removed

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourcesChangeEvent/session

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRInputSourcesChangeEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRLayer

In only one current engine.

FirefoxNoneSafariNoneChrome84+
Opera?Edge84+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

XRPose/angularVelocity

In no current engines.

FirefoxNoneSafariNoneChromeNone
Opera?EdgeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRPose/emulatedPosition

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRPose/linearVelocity

In no current engines.

FirefoxNoneSafariNoneChromeNone
Opera?EdgeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRPose/transform

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRPose

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpace/getOffsetReferenceSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpace/reset_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpace/reset_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpaceEvent/XRReferenceSpaceEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpaceEvent/referenceSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpaceEvent/transform

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRReferenceSpaceEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRenderState/baseLayer

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRenderState/depthFar

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRenderState/depthNear

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRenderState/inlineVerticalFieldOfView

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRenderState

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRRigidTransform/XRRigidTransform

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRigidTransform/inverse

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRigidTransform/matrix

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRigidTransform/orientation

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRigidTransform/position

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRRigidTransform

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/cancelAnimationFrame

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/end

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/end_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/end_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/inputSources

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/inputsourceschange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/inputsourceschange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/renderState

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/requestAnimationFrame

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/requestReferenceSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/select_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/select_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/selectend_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/selectend_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/selectstart_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/selectstart_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/squeeze_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/squeeze_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/squeezeend_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/squeezeend_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/squeezestart_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/squeezestart_event

In only one current engine.

FirefoxNoneSafariNoneChrome83+
Opera?Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSession/updateRenderState

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/visibilitychange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/visibilitychange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession/visibilityState

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSession

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSessionEvent/XRSessionEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSessionEvent/session

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSessionEvent

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSpace

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRSystem/devicechange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSystem/devicechange_event

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSystem/isSessionSupported

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSystem/requestSession

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRSystem

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRView/eye

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRView/recommendedViewportScale

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRView/requestViewportScale

In only one current engine.

FirefoxNoneSafariNoneChrome90+
Opera?Edge90+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRView

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewerPose/views

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewerPose

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewport/height

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewport/width

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewport/x

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewport/y

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRViewport

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/XRWebGLLayer

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/antialias

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/fixedFoveation

In no current engines.

FirefoxNoneSafariNoneChromeNone
Opera?EdgeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

XRWebGLLayer/framebuffer

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/framebufferHeight

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/framebufferWidth

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/getNativeFramebufferScaleFactor_static

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/getViewport

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer/ignoreDepthValues

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

XRWebGLLayer

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet11.2+Opera Mobile?
MDN

Headers/Feature-Policy/xr-spatial-tracking

In only one current engine.

FirefoxNoneSafariNoneChrome79+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone

Headers/Permissions-Policy/xr-spatial-tracking

In only one current engine.

FirefoxNoneSafariNoneChrome88+
Opera?Edge88+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera MobileNone