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

XRInputSourceXR入力 ソースを表し、これはユーザーがビューアと同じ 仮想空間で対象を指定したアクションを実行できるようにする任意の入力機構です。XR入力ソースの例には、 ハンドヘルドコントローラー、光学的に追跡される手、ならびにビューアのポーズに基づいて動作する視線ベースの入力方式などがありますが、 これらに限定されません。従来のゲームパッド、マウス、キーボードなど、XRデバイスに明示的に関連付けられていない入力機構は、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 Gamepads モジュールによっても拡張されます。

handedness 属性は、XR入力ソースが、 該当する場合にどちらの手に関連付けられているかを記述します。自然な利き手を持たない入力ソース (ヘッドセット搭載コントロールなど)、または利き手が現在不明な入力ソースは、この属性を "none" に設定しなければなりません。

targetRayMode 属性は、ターゲットレイを 生成するために使用される方法を記述し、必要に応じてアプリケーションがユーザーにターゲットレイをどのように 表示すべきかを示します。

targetRaySpace 属性は、XRSpace であり、 XRInputSource の推奨ポインティングレイの位置と向き(その -Z 軸に沿う)を追跡する ネイティブ原点 を持ち、これは targetRayMode によって定義されます。

targetRayMode"transient-pointer" である入力ソースでは、targetRaySpace は、インタラクション開始時にインタラクション対象へ向かうレイを表します。このポーズは、この XRInput の gripSpace 内で静的であるべきです。

gripSpace 属性は XRSpace であり、 仮想オブジェクトがユーザーの手に保持されているように見えるようレンダリングするために使用すべきポーズを追跡する ネイティブ原点 を持ちます。ユーザーがまっすぐな棒を握った場合、この XRSpace は、 ネイティブ原点 を曲げた指の重心に配置し、-Z 軸が棒の長さに沿って親指の方向を向くようにします。 X 軸は記述対象の手の甲に垂直であり、ユーザーの右手の甲は +X を向き、 左手の甲は -X を向きます。Y 軸は X 軸と Z 軸の 関係から暗黙的に決まり、+Y はおおむねユーザーの腕の方向を指します。

skipRendering 属性は、この入力が可視であり、 現在のセッションによってレンダリングする必要がない場合があることを示します。skipRendering が true で、targetRayMode が "tracked-pointer" の場合、ユーザーエージェントは、XR入力ソースの表現が常に ユーザーに表示されることを保証しなければなりません。

コントローラーがユーザーに表示される例には、コントローラーがディスプレイとユーザーの間にある場合、 ディスプレイが透明である場合、またはコントローラーがオペレーティングシステムによってレンダリングされる場合があります。

skipRendering は、コントローラーなどの入力ソースをレンダリングしないことに関する開発者へのヒントです。ピックレイとカーソルは 引き続きレンダリングすべきです。

targetRayMode"transient-pointer" である入力ソースでは、gripSpace は、関連付けられたユーザージェスチャーが存在する場合はそれであるべきで、存在しない場合は、ViewerSpace、 または別の XRInput の gripSpace や targetRaySpace など、ユーザーが制御する別の空間であるべきです。 これは、ユーザーが引き続き targetRaySpace を操作できるようにするためです。

gripSpace は、入力ソースが本質的に追跡可能でない場合、たとえば targetRayMode"gaze" または "screen" である入力ソースの場合、null でなければなりません。

profiles 属性は、入力ソースの推奨される視覚表現と 振る舞いの両方を示すリストであり、入力プロファイル 名を含みます。

入力プロファイル名は、空白を含まない ASCII 小文字の DOMString であり、複数の単語はハイフン(-)文字で連結されます。記述的な名前を選ぶべきであり、可能であれば デバイスベンダーが推奨する用語を使用します。プラットフォームが USB ベンダー ID や製品 ID などの適切な識別子を 提供する場合、それを使用してもよいです。シリアル番号など、単一のデバイスを一意に識別する値は 使用してはなりません。入力プロファイル名には、 デバイスの利き手を示す情報を含めてはなりません。複数のユーザーエージェントが同じデバイスを公開する場合、 同じ入力プロファイル名を報告するよう努めるべきです。WebXR Input Profiles レジストリは、入力プロファイル 名を管理する推奨場所です。

プロファイルは、具体性の高い順に指定されます。リストの最初のエントリ以降に指定される入力プロファイル 名は、デバイスの代替表現を示すフォールバック値を提供すべきです。これには、より汎用的な、または以前の バージョンのデバイス、十分に類似したより広く認識されているデバイス、あるいはデバイスタイプの大まかな説明 ("generic-trigger-touchpad" など)が含まれる場合があります。複数のプロファイルが指定される場合、 それらが記述するレイアウトは、リスト内の他のすべてのプロファイルのスーパーセットまたはサブセットでなければなりません。

XRSessionインラインセッションである場合、 profiles は空のリストでなければなりません。

ユーザーエージェントは、その裁量により、適切な汎用入力プロファイル 名のみ、または空のリストを報告することを選択してもよいです。これが適切なシナリオとしては、 入力デバイスを確実に識別できない場合、既知の入力プロファイルのいずれも入力デバイスに一致しない場合、 またはユーザーエージェントが使用中の入力デバイスを隠したい場合などがあります。

たとえば、Samsung HMD Odyssey のコントローラーは、標準的な Windows Mixed Reality コントローラーの設計バリエーションです。両方のコントローラーは同じ入力レイアウトを共有します。そのため、Samsung HMD Odyssey コントローラーの profiles は次のようになる可能性があります: ["samsung-odyssey", "microsoft-mixed-reality", "generic-trigger-squeeze-touchpad-thumbstick"]。 コントローラーの外観はリストの最初のプロファイルによって最も正確に伝えられ、2 番目のプロファイルは許容可能な 代替物を記述し、最後のプロファイルはデバイスを最も大まかに記述する汎用フォールバックです。 (トリガー、スクイーズボタン、タッチパッド、サムスティックを備えたコントローラーです。)
同様に、Valve Index コントローラーは HTC Vive コントローラーとの下位互換性がありますが、Index コントローラーには追加のボタンと軸があります。そのため、Valve Index コントローラーの profiles は次のようになる可能性があります: ["valve-index", "htc-vive", "generic-trigger-squeeze-touchpad-thumbstick"]。この場合、 "valve-index" プロファイルによって記述される入力レイアウトは、 "htc-vive" プロファイルによって記述されるレイアウトのスーパーセットです。また、 "valve-index" プロファイルはコントローラーの正確な外観を示しますが、 "htc-vive" コントローラーの外観は大きく異なります。この場合、UA はその違いを許容可能と 判断したことになります。そして最初の例と同様に、最後のプロファイルは汎用フォールバックです。
(正確な文字列は例にすぎません。実際のプロファイル名は WebXR Input Profiles レジストリで管理されます。)

注記: XRInputSource は、 XRSessioninputSources 配列内では「ライブ」です。そのため、その内部の値はその場で更新されます。これは、あるフレームで XRInputSource の 属性への参照を保存し、後続のフレームで同じ属性と比較して状態変化を検査する方法は機能しないことを意味します。 なぜなら、それらは同じオブジェクトだからです。したがって、フレーム間で入力状態を比較したい開発者は、 対象となる状態の内容をコピーすべきです。

XR入力ソースプライマリ入力 ソースであるのは、それが プライマリアクションをサポートする場合です。プライマリアクションは、実行されると selectstartselectend、 および select イベントを生成する、プラットフォーム固有のアクションです。可能なプライマリアクションの例には、トリガー、タッチパッド、またはボタンを押すこと、 コマンドを発話すること、あるいはハンドジェスチャーを行うことがあります。プラットフォームのガイドラインが推奨される プライマリ入力を定義している場合、それをプライマリ アクションとして使用すべきであり、そうでない場合、ユーザーエージェントは自由に 1 つを選択できます。 デバイスは少なくとも 1 つのプライマリ入力 ソースをサポートしなければなりません。

XR入力ソース追跡入力 ソースであるのは、それがプライマリアクションをサポートしない場合です。これらの入力は主としてポーズ データを提供することを目的としています。 注記: 追跡入力ソースの例としては、ユーザーの脚や小道具を追跡するための 追跡アタッチメントがあります。追跡される手も、プライマリアクションを検出するためのジェスチャー認識が行われていない場合、 追跡入力ソースと見なされる場合があります。

XRSession sessionXR入力 ソース source が、そのプライマリアクションを開始したとき、UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

  2. 名前 selectstart、 frame frame、source source入力ソース イベントを発火するタスクをキューに入れます

XRSession sessionXR入力 ソース source が、そのプライマリアクションを終了したとき、UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

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

    1. 名前 select、 frame frame、source source入力ソースイベントを発火します。

    2. 名前 selectend、 frame frame、source source入力ソースイベントを発火します。

XR入力ソースは、 プライマリ スクイーズアクションを定義してもよいです。プライマリスクイーズアクションは、実行されると squeezestartsqueezeend、 および squeeze イベントを生成するプラットフォーム固有のアクションです。プライマリスクイーズアクションは、概ね握る、またはつかむ動作に 対応するアクションに使用すべきです。可能なプライマリスクイーズアクションの例には、 グリップトリガーを押すことや、つかむハンドジェスチャーを行うことがあります。プラットフォームのガイドラインが推奨される プライマリスクイーズアクションを定義している場合、それをプライマリスクイーズアクションとして使用すべきであり、 そうでない場合、ユーザーエージェントは 1 つを選択してもよいです。

XRSession sessionXR入力 ソース source が、そのプライマリスクイーズアクションを開始したとき、UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

  2. 名前 squeezestart、 frame frame、source source入力ソース イベントを発火するタスクをキューに入れます

XRSession sessionXR入力 ソース source が、そのプライマリスクイーズアクションを終了したとき、UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

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

    1. 名前 squeeze、 frame frame、source source入力ソースイベントを発火します。

    2. 名前 squeezeend、 frame frame、source source入力ソースイベントを発火します。

プラットフォーム固有の振る舞いによって、プライマリアクションまたはプライマリスクイーズアクションが 中断またはキャンセルされることがあります。たとえば、XR入力ソースは、プライマリアクションまたはプライマリスクイーズ アクションが開始された後、終了する前にXRデバイスから削除される場合があります。

XRSession sessionXR入力 ソース sourceプライマリアクションがキャンセルされたとき、UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

  2. 名前 selectend、 frame frame、source sourceXRInputSourceEvent という入力ソースイベントを発火するタスクをキューに入れます

XRSession sessionXR入力 ソース sourceプライマリスクイーズアクションがキャンセルされたとき、UA は 次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsessiontime をアクションが発生した時刻とします。

  2. 名前 squeezeend、 frame frame、source sourceXRInputSourceEvent という入力ソースイベントを発火するタスクをキューに入れます

10.2. 一時入力

一部のXRデバイスは、一時入力 ソースをサポートする場合があります。この場合、XR入力ソースは、一時アクションを 実行している間だけ意味を持ちます。これは、プライマリ入力 ソースの場合はプライマリアクション、 または追跡入力ソースの場合はデバイス固有の 補助アクションです。

一例として、インラインセッションに対するマウス、タッチ、またはスタイラス入力があります。 これは targetRayModescreen に設定された一時的な XRInputSource を生成しなければならず、プライマリポインターについてはプライマリアクションとして扱われ、 非プライマリポインターについては非プライマリの補助アクションとして扱われます。

別の例として、直接公開できない機密情報から導出された入力を伴う、オペレーティングシステムからの意図があります。 たとえば視線に基づくインタラクションです。これらは targetRayModetransient-pointer に設定された一時的な XRInputSource を生成し、プライマリ アクションとして扱われます。

一時入力 ソースは、一時アクションの継続時間中のみ、セッションのアクティブな XR 入力ソースのリストに存在します。

一時入力 ソースは、非一時的なプライマリアクション用アルゴリズムの代わりに、一時アクションを処理する際に次のシーケンスに従います:

XRSession session一時入力ソース source が、その一時アクションを開始したとき、 UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsession とし、アクションが発生した時刻に対応させます。

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

    1. 必要に応じて、XR入力ソースのアクションによって 生成される "pointerdown" イベントをすべて発火します。

    2. XR入力ソースを追加し、アクティブな XR 入力ソースのリスト に入れます。

    3. 一時アクションプライマリアクションである場合、 名前 selectstart、 frame frame、source source入力ソースイベントを発火します。

XRSession session一時入力ソース source が、その一時アクションを終了したとき、 UA は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい 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 は次の手順を実行しなければなりません:

  1. frame を、session関連レルム内の新しい XRFrame とし、その sessionsession とし、アクションが発生した時刻に対応させます。

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

    1. 一時アクションプライマリアクションである場合、 名前 selectend、 frame frame、source source入力ソースイベントを発火します。

    2. XR入力ソースを削除し、アクティブな XR 入力ソースのリストから 取り除きます。

    3. 必要に応じて、XR入力ソースのアクションによって 生成される "pointerup" イベントをすべて発火します。

10.3. XRInputSourceArray

XRInputSourceArrayXRInputSourceリストを 表します。これは、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 {};

XRLayer は、 XRWebGLLayer および将来の拡張で導入されるその他のレイヤー型の基底クラスです。

11.2. XRWebGLLayer

XRWebGLLayer は、レンダリング先となる WebGL フレームバッファーを提供するレイヤーであり、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 = {});
  // 属性
  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;

  // メソッド
  XRViewport? getViewport(XRView view);

  // 静的メソッド
  static double getNativeFramebufferScaleFactor(XRSession session);
};

XRWebGLLayer は、初期値が nullcontext オブジェクトを持ち、これは WebGLRenderingContext または WebGL2RenderingContext のいずれかのインスタンスです。

XRWebGLLayer には、関連付けられた session があり、これは作成時に使用された XRSession です。

XRWebGLLayer(session, context, layerInit) コンストラクターは、呼び出されたときに次の手順を実行しなければなりません:

  1. layer を、session関連レルム内の新しい XRWebGLLayer とします。

  2. sessionended 値が true の場合、InvalidStateError をスローし、これらの手順を中止します。

  3. context が失われている場合、InvalidStateError をスローし、これらの手順を中止します。

  4. sessionイマーシブセッションであり、contextXR互換 ブール値が false の場合、InvalidStateError をスローし、これらの手順を中止します。

  5. layercontextcontext に初期化します。

  6. layersessionsession に初期化します。

  7. layerignoreDepthValues を次のように初期化します:

    layerInitignoreDepthValues 値が false であり、XRコンポジターが深度値を使用する場合:

    layerignoreDepthValuesfalse に初期化します。

    それ以外の場合:

    layerignoreDepthValuestrue に初期化します。

  8. layerコンポジション有効ブール値を次のように初期化します:

    sessionインラインセッションである場合:

    layerコンポジション有効false に初期化します。

    それ以外の場合:

    layerコンポジション有効ブール値を true に初期化します。

  9. layerコンポジション有効ブール値が true である場合:
    1. layerantialias を、layerInitantialias 値に初期化します。

    2. scaleFactorlayerInitframebufferScaleFactor とします。

    3. ユーザーエージェントは、ここで適切と判断する方法で scaleFactor をクランプまたは 丸めることを選択してもよいです。たとえば、性能上の理由からバッファー寸法を 2 のべき乗に 合わせたい場合などです。

    4. framebufferSize を、幅と高さをそれぞれ scaleFactor 倍した推奨 WebGL フレームバッファー解像度とします。

    5. layerframebuffer を、context関連レルム内の新しい WebGLFramebuffer に初期化します。これは、context で作成された寸法 framebufferSize不透明 フレームバッファーであり、sessionsession に初期化し、さらに layerInitdepthstencil、 および alpha 値を使用します。

    6. layer の合成をサポートするために必要な、GPU からアクセス可能な メモリーバッファーを含む、sessionXRデバイスと互換性のあるリソースを 割り当てて初期化します。

    7. 何らかの理由で layer のリソースを作成できなかった場合、OperationError をスローし、これらの手順を中止します。

    それ以外の場合:
    1. layerantialias を、layercontext実際のコンテキストパラメーターantialias 値に初期化します。

    2. layerframebuffernull に初期化します。

  10. layer を返します。

注記: XRWebGLLayerコンポジション有効ブール値が false に設定されている場合、XRWebGLLayerInit オブジェクト上のすべての値は無視されます。これは、WebGLRenderingContext のデフォルトフレームバッファーが、コンテキストの実際のコンテキストパラメーターを使用してすでに割り当てられており、 上書きできないためです。

context 属性は、XRWebGLLayer の作成時に使用された WebGLRenderingContext です。

XRWebGLLayer は、初期値が true に設定された コンポジション有効ブール値を持ちます。false に 設定されている場合、それは XRWebGLLayer が独自の WebGLFramebuffer を割り当ててはならず、XRWebGLLayerframebuffer プロパティを反映するすべてのプロパティは、代わりにcontext のデフォルトフレームバッファーのプロパティを 反映しなければならないことを示します。

XRWebGLLayerframebuffer 属性は、コンポジション 有効true の場合に不透明としてマークされた WebGLFramebuffer のインスタンスであり、それ以外の場合は null です。framebuffer のサイズは、XRWebGLLayer の作成後に開発者が調整することはできません。

不透明 フレームバッファーは、標準の WebGLFramebuffer と同様に機能しますが、デフォルト フレームバッファーにより近い振る舞いにするため、次の変更があります:

注記: ユーザーエージェントは、 depth および stenciltrue 値を尊重する必要があり、これは WebGL が描画バッファーを作成する際の振る舞いと類似しています。

不透明フレームバッファーにアタッチされたバッファーは、 最初に作成されたとき、または各XRアニメーションフレームの処理前に、 下の表の値へクリアされなければなりません。これは WebGL コンテキストのデフォルト フレームバッファーの振る舞いと同一です。不透明フレームバッファーは、関連付けられた WebGL コンテキストの preserveDrawingBuffer 値に関係なく常にクリアされます。

バッファー クリア値
カラー (0, 0, 0, 0)
深度 1.0
ステンシル 0

注記: 実装は、開発者が別プロセスのバッファー内容へ アクセスできないことを保証できる限り、不透明フレームバッファーで要求される暗黙のクリア操作を 最適化によって省略してもよいです。たとえば、開発者が明示的なクリアを実行した場合、暗黙のクリアは不要です。

XRWebGLLayeralphatrue に設定して作成された場合、framebufferRGBA カラーフォーマットのテクスチャーによって裏付けられなければなりません。 XRWebGLLayeralphafalse に設定して作成された場合、framebufferRGB カラーフォーマットのテクスチャーによって裏付けられなければなりません。

ただし、XRコンポジターは、 framebuffer を裏付けるピクセルを、SRGB8_ALPHA8 または SRGB8colorFormat であるかのように扱わなければなりません。

注記: これは、XRコンポジターが、framebuffer を裏付けるテクスチャーを処理するとき、線形 RGBA または RGB からいかなるガンマ変換も行ってはならないことを意味します。そうしない場合、最終レンダリングのピクセルが 明るすぎて見え、通常の 2D WebGLRenderingContext コンテキストでのレンダリングと一致しなくなります。

XRWebGLLayerイマーシブ セッションbaseLayer として設定されると、不透明フレームバッファーの内容は、XRアニメーション フレームの完了直後にイマーシブ XR デバイスへ提示されますが、前のXRアニメーションフレーム以降に 次の少なくとも 1 つが発生している場合に限ります:

不透明 フレームバッファーイマーシブ XR デバイスへ提示される前に、ユーザーエージェントは すべてのレンダリング操作が不透明フレームバッファーへフラッシュ済みであることを 保証しなければなりません。

XRWebGLLayerターゲットフレームバッファーを持ちます。これはコンポジション有効true の場合は framebuffer であり、それ以外の場合はcontext の デフォルトフレームバッファーです。

framebufferWidth および framebufferHeight 属性は、それぞれ ターゲットフレームバッファーのアタッチメントの幅と高さを返します。

antialias 属性は、ターゲットフレームバッファーが UA の選択する手法を使用した アンチエイリアスをサポートする場合は true、アンチエイリアスが行われない場合は false です。

ignoreDepthValues 属性が true の場合、XRコンポジターはレンダリング時に深度バッファーアタッチメント内の値を 使用してはならないことを示します。この属性が false の場合、深度バッファーアタッチメントの内容が XRコンポジターによって使用され、レイヤーにレンダリングされたシーンを 表すことが期待されることを示します。

バッファーに格納される深度値は 0.0 から 1.0 の間であることが期待され、 0.0depthNear の距離を表し、1.0depthFar の距離を表し、中間値は線形補間されます。これは WebGL のデフォルトの振る舞いです。(追加の詳細については、 depthRange 関数のドキュメントを参照してください。)

注記: シーンの深度バッファーをコンポジターで利用可能にすると、 一部のプラットフォームでは、改善された再投影など、品質や快適性の向上を実現できます。

fixedFoveation 属性は、XR コンポジターが使用するフォビエーションの量を制御します。ユーザーエージェントまたはデバイスがこの属性を サポートしない場合、取得時には null を返し、設定は no-op とすべきです。fixedFoveation0 未満の値に設定すると 0 に設定され、1 より大きい値に設定すると 1 に設定されます。0 はフォビエーションの最小量を設定し、 1 は最大量を設定します。XRコンポジターがこれらの値をどのように解釈するかは ユーザーエージェントに委ねられます。fixedFoveation レベルが変更された場合、次の XRFrame で有効になります。

注記: 固定フォビエーションは、ユーザーの視野の端付近で コンテンツをレンダリングする解像度を低下させる手法です。GPU のフィル性能によって制限される体験を大幅に改善できます。 消費電力を削減し、アプリケーションがアイテクスチャーの解像度を高められるようにします。背景画像などの 低コントラストテクスチャーには最も有用ですが、テキストや詳細な画像などの高コントラストなものにはそれほど有用ではありません。 作者は、性能と視覚品質の最適なトレードオフを得るために、フレームごとにレベルを調整できます。

XRWebGLLayer は、フルサイズビューポートのリストを持たなければなりません。これは、 XRSession が 公開する可能性のある各ビューについて 1 つのWebGL ビューポートを含むリストです。これには、 現在はアクティブでないものの、現在のセッションでアクティブになる可能性があるセカンダリ ビューも含まれます。ビューポートは width および height0 より大きくなければならず、ターゲットフレームバッファーの境界を超えない矩形を 記述しなければなりません。ビューポートは重なってはなりません。

コンポジション有効false であり、 sessionビューの リストに、eye"none" である単一のビューが含まれる場合、 フルサイズビューポートのリストには、context の デフォルトフレームバッファー全体を覆う単一のWebGL ビューポートが含まれなければなりません。

コンポジション有効false であり、 sessionビューの リストに 2 つのプライマリ ビュー、すなわち一方はeye"left" で、もう一方はeye"right" であるものが含まれる場合、フルサイズビューポートのリストには 2 つのWebGL ビューポート、すなわち "left" ビューに関連付けられたものと、"right" ビューに関連付けられたものが含まれなければなりません。 ユーザーエージェントは、上記の制約に従ってこれらのビューポートのサイズと位置を決定します。

注記: この仕様では、ステレオのインラインビューポートについて、 横並びなど特定のパッキングを要求しません。作者は、レイアウトを仮定するのではなく、各 XRView に対して getViewport() を使用すべきです。

XRWebGLLayer は、ビューポート オブジェクトのリストを持たなければなりません。これは、XRSession が 現在公開している各アクティブビューについて 1 つの XRViewport を含むリストです。

getViewport() は、指定された XRView がレイヤーへのレンダリング時に使用すべき XRViewport を照会します。

getViewport(view) メソッドは、 XRWebGLLayer layer に対して呼び出されたとき、次の手順を実行しなければなりません:

  1. sessionviewsession とします。

  2. framesessionアニメーション フレームとします。

  3. sessionlayersession と等しくない場合、 InvalidStateError をスローし、これらの手順を中止します。

  4. frameactive ブール値が false の場合、InvalidStateError をスローし、これらの手順を中止します。

  5. viewframeframe と等しくない場合、InvalidStateError をスローし、これらの手順を中止します。

  6. ビューポート変更可能フラグが true であり、 view要求されたビューポートスケール現在のビューポートスケールと等しくない場合:

    1. 現在のビューポートスケール要求されたビューポートスケールに設定します。

    2. ビューポートオブジェクトのリスト内で、 view に関連付けられた XRViewport を、session について view に関連付けられたフルサイズビューポートのリストからスケーリングされたビューポートを取得した結果の XRViewport に設定します。

  7. viewビューポート変更可能フラグを false に設定します。

  8. viewport を、ビューポートオブジェクトのリスト内で view に関連付けられた XRViewport とします。

  9. viewport を返します。

注記: ビューポート変更可能フラグは、 現在のビューポート スケールに変更がなかった場合でも、意図的に false に設定されます。これにより、 getViewport(view) の呼び出しは、そのビューのアニメーションフレーム内で常に一貫した結果を 返し、最初に取得された値がフレームの残りの期間にわたって固定されます。アプリケーションが requestViewportScale()getViewport() の後で呼び出した場合、要求された値は、将来のフレームで getViewport() が再び呼び出されたときにのみ適用されます。

XRSession は、ネイティブ WebGL フレームバッファー解像度を 特定しなければなりません。これは、XRデバイスの物理ピクセル解像度に 一致するために必要な WebGL フレームバッファーのピクセル解像度です。

XRSession sessionネイティブ WebGL フレームバッファー解像度は、 次の手順を実行することで決定されます:

  1. sessionインラインセッションである場合、ネイティブ WebGL フレームバッファー解像度を、 sessionrenderState出力 canvasの物理ディスプレイピクセル単位のサイズに設定し、 canvas のサイズが変更されるたび、または出力 canvasが変更されるたびにこれらの手順を再評価し、これらの手順を中止します。

  2. ネイティブ WebGL フレームバッファー解像度を、 セッションのすべての XRView を収容できる十分な大きさのフレームバッファーのピクセルと、最大倍率となるディスプレイ領域の 物理スクリーンピクセルとの間が 1:1 の比率になるために必要な解像度に設定します。記述した方法で ネイティブ解像度を決定する手段が存在しない場合、推奨 WebGL フレームバッファー 解像度を使用してもよいです。

さらに、XRSession推奨 WebGL フレームバッファー解像度を 特定しなければなりません。これは、セッションのすべての XRView を 収容するのに十分な大きさで、平均的なアプリケーションに性能と品質の良好なバランスを提供する WebGL フレームバッファー解像度の最適な推定値を表します。これは、ネイティブ WebGL フレームバッファー解像度より 小さくても、大きくても、等しくてもよいです。新しい不透明フレームバッファー はこの解像度で作成され、幅と高さはそれぞれ、指定された XRWebGLLayerInitframebufferScaleFactor によってスケーリングされます。

注記: ユーザーエージェントは、 推奨 WebGL フレームバッファー解像度を 推定するために任意の方法を自由に使用できます。推奨サイズを照会するためのプラットフォーム固有の方法がある場合は、 それを使用することが推奨されますが、必須ではありません。framebufferScaleFactor および getNativeFramebufferScaleFactor() が使用するスケール係数は幅と高さに個別に適用されるため、スケール係数が 2 の場合、全体のピクセル数は 4 倍になります。 プラットフォームがピクセル数に基づく面積ベースのレンダースケールを公開する場合、ユーザーエージェントは、 それを WebXR スケール係数へ変換するために平方根を取る必要があります。

getNativeFramebufferScaleFactor(session) メソッドは、呼び出されたときに次の手順を実行しなければなりません:

  1. sessionthis とします。

  2. sessionended 値が true の場合、0.0 を返し、これらの手順を中止します。

  3. session推奨 WebGL フレームバッファー 解像度の幅と高さのそれぞれに掛けることで、sessionネイティブ WebGL フレームバッファー解像度 が得られる値を返します。

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