1. はじめに
バーチャルリアリティ(VR)や拡張現実(AR)アプリケーションを実現するハードウェアは、現在では消費者向けにも広く提供されており、没入型コンピューティングプラットフォームとして新たな機会と課題の両方をもたらしています。没入型ハードウェアと直接やり取りできる能力は、ウェブがこの環境で一級市民として機能するために極めて重要です。
没入型コンピューティングは、満足のいく体験を提供するために高精度かつ低遅延の通信が厳しく求められます。また、ウェブのようなプラットフォームに特有のセキュリティ上の懸念も生じます。WebXR Device APIは、開発者がさまざまなハードウェア形態に対応した魅力的で快適かつ安全な没入型アプリケーションをウェブ上で構築するために必要なインターフェイスを提供します。
他のウェブインターフェイス、たとえばRelativeOrientationSensor
や AbsoluteOrientationSensor
などは、一部のデバイスからの入力を取得して、限定的な状況でWebXR Device APIのポリフィルとして利用されることがあります。しかし、これらのインターフェイスは、6DoFトラッキングやヘッドセット周辺機器への表示、トラッキング入力デバイスなど、高度な没入型体験の複数の機能をサポートできません。
1.1. 用語
本書ではXRという略語を、バーチャルリアリティ、拡張現実、およびその他関連技術のために使用されるハードウェア、アプリケーション、手法の総称として用いています。例として、以下が挙げられますが、これらに限りません:
-
ヘッドマウントディスプレイ(不透明・透明・ビデオパススルー対応を含む)
-
位置トラッキング付きモバイルデバイス
-
ヘッドトラッキング機能を有する固定ディスプレイ
これらに共通する重要な特徴は、仮想コンテンツのビューをシミュレートするための空間トラッキングを何らかの形で提供する点です。
「XRデバイス」「XRアプリケーション」などの用語は、一般的に上記のいずれにも適用されるものと理解されます。本書のうち、これらのデバイスの一部にのみ該当する部分については、適切にその旨が示されます。
3DoF や 6DoF という用語は、本書全体を通してXRデバイスのトラッキング機能を表すために使用されます。
-
3DoF デバイス("Three Degrees of Freedom" の略)は、回転運動のみをトラッキングできるデバイスを指します。これは、加速度センサーやジャイロスコープのみでトラッキングを行うデバイスによく見られます。3DoF デバイスはユーザーの並進運動には反応しませんが、首や腕のモデル化に基づくアルゴリズムで並進変化を推定する場合もあります。
-
6DoF デバイス("Six Degrees of Freedom" の略)は、回転と並進の両方をトラッキングでき、空間内での正確な1:1トラッキングを可能とします。これには、ユーザーの環境に関する一定程度の理解が求められます。その環境理解は、トラッキング対象デバイス自体に搭載されたセンサー(カメラや深度センサーなど)を使って位置を判断するインサイドアウトトラッキングや、ユーザーの環境に設置された外部装置(カメラや発光装置など)を基準点としてXRデバイスが自身の位置を決定するアウトサイドイントラッキングによって実現されます。
1.2. アプリケーションの流れ
WebXR Device APIを利用するほとんどのアプリケーションは、次のような利用パターンに従います:
-
ハードウェアとUAが希望する種類のXRコンテンツをサポートしているかどうかを判定するために、
navigator.xr.isSessionSupported()
を問い合わせます。 -
サポートされていれば、ユーザーにXRコンテンツを案内します。
-
ウィンドウが一時的なアクティベーション状態になるのを待ちます。これは、多くの場合、ユーザーがページ上のボタンをクリックしてXRコンテンツの表示を開始したい意思を示すことで表されます。
-
ユーザーアクティベーションイベント内で、
XRSession
をnavigator.xr.requestSession()
によってリクエストします。 -
XRSession
のリクエストが成功した場合、それを用いてフレームループを実行し、XR入力への応答やXRデバイスへの画像生成表示を行います。
2. モデル
2.1. XRデバイス
XRデバイスとは、ユーザーに没入型コンテンツを提示できる物理的なハードウェアユニットを指します。コンテンツが「没入型」と見なされるのは、視覚・聴覚・触覚またはその他の感覚出力によってユーザーの環境の様々な要素をシミュレートまたは拡張する場合です。多くの場合、これはユーザーの空間的な動きをトラッキングし、その動きと同期した出力を生成することを伴います。デスクトップクライアントでは通常ヘッドセット周辺機器であり、モバイルクライアントではビューアーハーネスと組み合わせてモバイルデバイス自体を表す場合もあります。ステレオ表示機能は無いが高度なトラッキングを備えたデバイスも含まれます。
XRデバイスは、対応モードのリスト(リスト(文字列))を持ち、そのリストには、そのXRデバイスがサポートするXRSessionMode
の列挙値が含まれます。
各XRデバイスは、対応モードごとにXRSessionMode
に対して許可された機能のセットを持ちます。これはセットであり、機能記述子のセットで、初期状態では空のセットでなければなりません。
ユーザーエージェントは、没入型XRデバイスのリスト(リスト(XRデバイス))を持ち、初期状態では空のリストでなければなりません。
ユーザーエージェントは、没入型XRデバイス(null
またはXRデバイス)を持ちます。これは初期状態ではnull
であり、没入型XRデバイスのリストから選ばれるアクティブなXRデバイスを表します。このオブジェクトは別スレッド上に存在し、非同期に更新されることがあります。
ユーザーエージェントは、デフォルトインラインXRデバイスを持たなければなりません。これはXRデバイスであり、その対応モードのリストに"inline"
を含んでいなければなりません。デフォルトインラインXRデバイスは、ポーズ情報を報告してはならず、ポインターイベントによって生成されるもの以外のXR入力ソースやイベントを報告してはなりません。
注記: デフォルトインラインXRデバイスは、開発者の利便性のために存在し、インライン/没入型の両方のコンテンツで同じ描画・入力ロジックを利用できるようにします。デフォルトインラインXRデバイスは、ページ上の他の仕組み(入力用のポインターイベントなど)を通じて既に開発者が利用できる情報以外を公開しません。単にXR中心の形式で値を提供するだけです。
ユーザーエージェントは、インラインXRデバイスを持たなければなりません。これはXRデバイスであり、その対応モードのリストに"inline"
を含んでいなければなりません。インラインXRデバイスは、そのトラッキングがインラインコンテンツに公開するのが適切であれば没入型XRデバイスと同一であってもよく、そうでなければデフォルトインラインXRデバイスでなければなりません。
注記: スマートフォンでは、インラインXRデバイスはジャイロスコープや加速度センサーなどの内部センサーから導出されたポーズ情報を報告する場合があります。類似センサーのないデスクトップやノートパソコンでは、インラインXRデバイスはポーズを報告できず、その場合デフォルトインラインXRデバイスにフォールバックすべきです。既にXRデバイス上でユーザーエージェントが動作している場合、インラインXRデバイスは同じデバイスとなり、複数のビューをサポートすることがあります。デフォルトインラインXRデバイスが公開する機能を超えるトラッキングや入力機能を提供する場合は、ユーザーの同意が必要です。
現在の没入型XRデバイスのリスト、インラインXRデバイス、没入型XRデバイスの値は、別スレッド上で非同期に更新されることがあります。これらのオブジェクトは、並列実行していない手順から直接アクセスすべきではありません。
3. 初期化
3.1. navigator.xr
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute XRSystem xr ; };
xr
属性のgetterは、それに関連付けられたXRSystem
オブジェクトを返さなければなりません。
3.2. XRSystem
[SecureContext ,Exposed =Window ]interface :
XRSystem EventTarget { // MethodsPromise <boolean >isSessionSupported (XRSessionMode ); [
mode NewObject ]Promise <XRSession >requestSession (XRSessionMode ,
mode optional XRSessionInit = {}); // Events
options attribute EventHandler ondevicechange ; };
ユーザーエージェントは、XRSystem
オブジェクトをNavigator
オブジェクトの作成時に生成し、そのオブジェクトに関連付けなければなりません。
XRSystem
オブジェクトはAPIのエントリーポイントであり、ユーザーエージェントで利用可能なXR機能の問い合わせや、XRSession
の生成を通じてXRハードウェアとの通信を開始するために使用されます。
ユーザーエージェントは、システムに接続された没入型XRデバイスの列挙ができなければなりません。このとき、利用可能な各デバイスは没入型XRデバイスのリストに追加されます。その後の列挙要求アルゴリズムは、キャッシュされた没入型XRデバイスのリストを再利用しなければなりません。デバイスの列挙はデバイストラッキングを初期化すべきではありません。最初の列挙後、ユーザーエージェントはデバイスの接続・切断を監視し、接続されたデバイスを没入型XRデバイスのリストに追加し、切断されたデバイスを除外します。
没入型XRデバイスのリストが変更されるたびに、ユーザーエージェントは次の手順で没入型XRデバイスの選択を行うべきです:
-
oldDeviceを没入型XRデバイスとする。
-
没入型XRデバイスのリストが空のリストである場合、没入型XRデバイスを
null
に設定する。 -
没入型XRデバイスのリストのサイズが1の場合、没入型XRデバイスを没入型XRデバイスのリスト[0]に設定する。
-
没入型XRデバイスを以下のように設定する:
- アクティブな
XRSession
が存在し、かつ没入型XRデバイスのリストがoldDeviceを含む場合: -
没入型XRデバイスをoldDeviceに設定する。
- それ以外の場合:
-
ユーザーエージェントが選択したデバイスを没入型XRデバイスに設定する。
- アクティブな
-
必要に応じて、インラインXRデバイスを没入型XRデバイスに更新するか、そうでなければデフォルトインラインXRデバイスに設定してもよい。
-
これが初回のデバイス列挙である場合、またはoldDeviceが没入型XRデバイスと等しい場合、これ以降の手順を中止する。
-
タスクをキューし、全ての
WebGLRenderingContextBase
インスタンスのXR compatible
ブール値をfalse
に設定する。 -
タスクをキューし、イベントdevicechangeを、該当するGlobal objectの
navigator
のxr
に発火する。 -
タスクをキューし、没入型XRデバイスやインラインXRデバイスの変更によって影響を受ける全ての
XRPermissionStatus
オブジェクトに適切なchange
イベントを発火する。
注記: これらの手順は常に並列で実行されるべきです。
注記: 没入型XRデバイスのリストに複数のデバイスが含まれている場合、ユーザーエージェントは任意の基準で没入型XRデバイスを選択できます。例えば、常にリストの先頭のデバイスを選択したり、ユーザーがデバイスの優先度を管理できる設定UIを提供しても構いません。理想的には、デフォルトデバイスを選択するアルゴリズムは安定していて、複数回のブラウジングセッションでも同じデバイスが選択される結果となるべきです。
ユーザーエージェントは、次の手順を実行することで没入型XRデバイスが選択されていることを保証できます:
-
没入型XRデバイスを列挙する。
-
没入型XRデバイスを選択する。
-
没入型XRデバイスを返す。
注記: これらの手順は常に並列で実行されるべきです。
ondevicechange
属性は、イベントハンドラーIDL属性であり、devicechangeイベントタイプのためのものです。
isSessionSupported(mode)
メソッドは、指定されたmodeがユーザーエージェントおよびデバイス機能によってサポートされる可能性があるかどうかを問い合わせます。
このメソッドが呼び出されたとき、次の手順を実行しなければなりません:
-
promiseを、この
XRSystem
の関連realmで新しいPromiseとする。 -
要求元ドキュメントのオリジンが"xr-spatial-tracking"permissions policyの利用を許可されていない場合、reject promiseを"
SecurityError
"DOMException
で拒否し、返す。 -
セッションmodeがサポートされているかどうかを次のように確認する:
- ユーザーエージェントおよびシステムがmodeセッションを決してサポートしないことが分かっている場合
-
resolve promiseを
false
で解決する。 - ユーザーエージェントおよびシステムがmodeセッションを通常サポートすることが分かっている場合
-
このユーザーエージェントの全てのUA文字列で区別できないインスタンスがここで同じ結果を返す場合に限り、promiseを
true
で解決してもよい。 - それ以外の場合
-
次の手順を並列で実行する:
-
deviceを没入型XRデバイスが選択されていることを保証した結果とする。
-
deviceがnullの場合、resolve promiseを
false
で解決し、これ以降の手順を中止する。 -
deviceの対応モードのリストがmodeを含まない場合、タスクをキューし、resolve promiseを
false
で解決し、これ以降の手順を中止する。 -
強力な機能"xr-session-supported"の利用許可を、
XRSessionSupportedPermissionDescriptor
のmode
にmodeを指定してリクエストする。"denied"
が返された場合は、タスクをキューし、resolve promiseをfalse
で解決し、これ以降の手順を中止する。詳細はフィンガープリンティングに関する考慮を参照。
-
-
promiseを返す。
注記: isSessionSupported()
の目的は、ユーザーエージェントがXRSession
を作成できるかを完全に正確に報告することではなく、指定のmodeセッションを作成できる旨を案内すべきかどうかをページに通知することです。必要なハードウェアやソフトウェアを事前に確認しても、ある程度の偽陽性が発生することがあります(例えば、適切なハードウェアが存在していても、セッション要求時に他のアプリケーションに排他的アクセス権が与えられている場合など)。
ほとんどのXRコンテンツを含むページは、ドキュメントのライフサイクルの早い段階でisSessionSupported()
を呼び出すことが想定されます。そのため、isSessionSupported()
の呼び出しでは、モーダルUIやその他ユーザーの操作を妨げるUIを表示すべきではありません。isSessionSupported()
の呼び出しは、デバイス選択UIを表示してはならず、システム上で実行中のXRアプリケーションを妨げてはならず、システムトレイやストアフロント等XR関連アプリケーションを起動させてはなりません。
immersive-vr
セッションがサポートされているかどうかを確認します。
const supported= await navigator. xr. isSessionSupported( 'immersive-vr' ); if ( supported) { // 'immersive-vr' セッションがサポートされている可能性があります。 // ページはユーザーへサポートを案内すべきです。 } else { // 'immersive-vr' セッションはサポートされていません。 }
XRSystem
オブジェクトは、未処理の没入型セッションブール値(初期値はfalse
)、アクティブな没入型セッション(初期値はnull
)、およびインラインセッションのリスト(初期値は空)を持ちます。
requestSession(mode, options)
メソッドは、可能であれば指定したmodeでXRSession
を初期化し、必要に応じて没入型モードに入ろうとします。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
promiseを、この
XRSystem
の関連realmで新しいPromiseとする。 -
modeが没入型セッションモードであればimmersiveを
true
、それ以外はfalse
とする。 -
global objectを、このメソッドが呼び出された
XRSystem
の該当するGlobal objectとする。 -
セッション要求が許可されているかを次のように確認する:
- immersiveが
true
の場合: -
-
没入型セッション要求が許可されているか確認し、許可されていなければreject promiseを"
SecurityError
"DOMException
で拒否し、promiseを返す。 -
未処理の没入型セッションが
true
またはアクティブな没入型セッションがnull
でない場合、reject promiseを"InvalidStateError
"DOMException
で拒否し、promiseを返す。 -
未処理の没入型セッションを
true
に設定する。
-
- それ以外の場合:
-
インラインセッション要求が許可されているか確認し、許可されていなければreject promiseを"
SecurityError
"DOMException
で拒否し、promiseを返す。
- immersiveが
-
次の手順を並列で実行する:
-
requiredFeaturesをoptionsの
requiredFeatures
とする。 -
optionalFeaturesをoptionsの
optionalFeatures
とする。 -
deviceをmode、requiredFeatures、optionalFeaturesに対する現在のデバイスの取得結果とする。
-
タスクをキューし、以下の手順を実行する:
-
deviceが
null
またはdeviceの対応モードのリストがmodeを含まない場合、以下の手順を実行する:-
reject promiseを"
NotSupportedError
"DOMException
で拒否する。 -
immersiveが
true
の場合、未処理の没入型セッションをfalse
に設定する。 -
これ以降の手順を中止する。
-
-
descriptorにmode、requiredFeatures、optionalFeaturesで初期化した
XRPermissionDescriptor
を設定する。 -
statusに初期値
null
のXRPermissionStatus
を設定する。 -
xrパーミッションを要求し、descriptorとstatusを指定する。
-
statusの
state
が"denied"
の場合、以下の手順を実行する:-
reject promiseを"
NotSupportedError
"DOMException
で拒否する。 -
immersiveが
true
の場合、未処理の没入型セッションをfalse
に設定する。 -
これ以降の手順を中止する。
-
-
セッションの初期化をsession, mode, granted, deviceで実施する。
-
アクティブな没入型セッションを次のように設定する場合がある:
- immersiveが
true
の場合: -
アクティブな没入型セッションをsessionに設定し、未処理の没入型セッションを
false
に設定する。 - それ以外の場合:
-
sessionをインラインセッションのリストに追加する。
- immersiveが
-
resolve promiseをsessionで解決する。
-
タスクをキューし、以下の手順を実施する:
注記: これらの手順は、初回のinputsourceschange
イベントがセッションの解決後に発生するようにするためのものです。-
sessionのpromise resolvedフラグを
true
に設定する。 -
sourcesをsessionに接続されている既存の入力ソースとする。
-
sourcesが空でない場合、以下の手順を実施する:
-
sessionのアクティブなXR入力ソースのリストをsourcesに設定する。
-
session上で、
XRInputSourcesChangeEvent
イベントinputsourceschange
をadded
にsourcesを設定して発火する。
-
-
-
-
-
promiseを返す。
XRSessionMode
mode、requiredFeatures、optionalFeaturesに対してユーザーエージェントが現在のデバイスを取得するには、次の手順を実行しなければなりません:
-
deviceを次のように選択する:
- modeが没入型セッションモードの場合:
-
deviceに没入型XRデバイスが選択されていることを保証した結果を設定する。
- requiredFeaturesまたはoptionalFeaturesが空でない場合:
-
deviceをインラインXRデバイスに設定する。
- それ以外の場合:
-
deviceをデフォルトインラインXRデバイスに設定する。
-
deviceを返す。
注記: これらの手順は常に並列で実行されるべきです。
immersive-vr
XRSession
の取得を試みます。
const xrSession= await navigator. xr. requestSession( "immersive-vr" );
3.3. XRSessionMode
XRSessionMode
列挙型は、XRSession
が動作できるモードを定義します。
enum {
XRSessionMode "inline" ,"immersive-vr" ,"immersive-ar" };
-
inline
モードは、セッションの出力がHTMLドキュメント内の要素として表示されることを示します。inline
セッションのコンテンツはモノ(すなわち、単一のview)で表示されなければなりません。また、viewerトラッキングを許可しても構いません。ユーザーエージェントはinline
セッションの作成を必ず許可しなければなりません。 -
immersive-vr
モードは、セッションの出力が排他的アクセスで没入型XRデバイスのディスプレイに表示され、コンテンツがユーザーの環境と統合されることを意図していないことを示します。 -
immersive-ar
モードの動作は WebXR AR Module で定義されており、UAがそのモジュールを実装していない限り、没入型XRデバイスの対応モードのリストに追加してはなりません。
本書では、インラインセッションはinline
セッションと同義であり、没入型セッションはimmersive-vr
またはimmersive-ar
セッションを指します。
イマーシブセッションは、必ず何らかのレベルのビューアトラッキングを提供しなければならず、コンテンツはユーザーおよび/または周囲の環境に対して適切なスケールで表示されなければなりません。さらに、イマーシブセッションはイマーシブXRデバイスへの排他的アクセスを必ず付与されなければなりません。つまり、イマーシブセッションが
"visible"
の間、HTMLドキュメントはイマーシブXRデバイスのディスプレイに表示されず、他のソースのコンテンツが排他的アクセスを持つこともありません。排他的アクセスはユーザーエージェント自身のUIオーバーレイを妨げるものではありませんが、このUIは最小限であるべきです。
注記: UAはアクセシビリティや安全性のために、ガーディアン境界・障害物・入力手段がない場合はユーザーの手などを重ねて表示することがあります。
注記: 将来の仕様やモジュールにより、没入型セッションの定義に追加のセッションモードが加わる場合があります。
注記: 排他的アクセスが提供される例として、VRヘッドセットでのステレオコンテンツ表示などが挙げられます。
注記: オーバーレイUIの例として、没入型セッション中にユーザーエージェントやOSが通知を描画コンテンツの上に表示することがあります。
注記: 没入型XRデバイスのディスプレイでは没入型セッション中にHTMLドキュメントは表示されませんが、別のディスプレイ(たとえばPCの2Dブラウザから没入型セッションを開始した場合など)では表示されることがあります。
3.4. 機能の依存関係
XRSession
の一部の機能は、様々な理由で普遍的に利用可能でない場合があります。その理由には、すべてのXRデバイスがすべての機能に対応できるわけではない点が含まれます。もう一つの考慮点は、いくつかの機能が機微な情報を公開するため、動作前に明確なユーザーの意図のシグナルが必要となる場合があることです。
基盤となるXRプラットフォームを初期化しXRSession
を作成しても、すぐにアプリケーションが正しく動作できないことをユーザーに通知するのは悪いユーザー体験であるため、開発者は必須機能をXRSessionInit
辞書をrequestSession()
に渡すことで指定できます。
これにより、必須機能のいずれかがデバイスの制限やユーザーの意図の明確なシグナルがない場合に利用できなければ、XRSession
の作成をブロックします。
また、開発者はより高機能なデバイスで機能が段階的に向上する体験を設計することが推奨されます。オプション機能(必須ではないが利用可能であれば利用する機能)も、XRSessionInit
辞書内で指定し、必要に応じてユーザーの意図が確認されてから有効化できるようにすべきです。
dictionary {
XRSessionInit sequence <DOMString >requiredFeatures ;sequence <DOMString >optionalFeatures ; };
requiredFeatures
配列は体験における必須機能を含みます。リスト内のいずれかの値が認識されていない機能記述子であれば、XRSession
は作成されません。requiredFeatures
配列内の機能のいずれかがXRデバイスでサポートされていない、または必要に応じてユーザーの意図の明確なシグナルがない場合、XRSession
は作成されません。
optionalFeatures
配列は体験におけるオプション機能を含みます。リスト内のいずれかの値が認識されていない機能記述子であれば無視されます。optionalFeatures
配列内で指定された機能は、XRデバイスでサポートされ、かつ必要に応じてユーザーの意図が明確であれば有効化されますが、存在しなくてもXRSession
の作成を妨げません。
機能リストに指定された値は、以下のいずれかに該当すれば有効な機能記述子とみなされます:
-
XRReferenceSpaceType
列挙値の文字列表現
今後の本仕様のバージョンや追加モジュールによって、受け付け可能な機能記述子のリストが拡張される場合があります。
注記: 追加の初期化が必要な機能がある場合、XRSessionInit
にその機能用の新しいフィールドを追加すべきです。
リクエストされたXRSessionMode
によって、特定の機能記述子がrequiredFeatures
またはoptionalFeatures
リストにデフォルトで追加されます。次の表は、各セッションタイプと機能リストに対応するデフォルト機能を示します:
機能 | セッション | リスト |
---|---|---|
"viewer"
| インラインセッション および 没入型セッション | requiredFeatures
|
"local"
| 没入型セッション | requiredFeatures
|
requiredFeatures
およびoptionalFeatures
で指定された機能記述子の組み合わせは、そのXRSession
のリクエスト機能とみなされます。
一部の機能記述子は、リクエスト機能リストに含まれる場合、permissions policyや、ユーザーの意図が明確である(明示的同意または黙示的同意による)ことが有効化の要件となります。次の表は有効化前に満たすべき機能要件を示します:
機能 | Permissions Policy 必須 | 同意 必須 |
---|---|---|
"local"
| "xr-spatial-tracking" | インラインセッション は同意が必要 |
"local-floor"
| "xr-spatial-tracking" | 常に同意が必要 |
"bounded-floor"
| "xr-spatial-tracking" | 常に同意が必要 |
"unbounded"
| "xr-spatial-tracking" | 常に同意が必要 |
注記: "local"
は、没入型セッションのリクエスト機能に常にデフォルト機能として含まれており、したがって没入型セッションでは常に明示的同意または黙示的同意を得る必要があります。
リクエスト機能 は、そのXRデバイスがサポート可能である場合にのみセッションで有効化できます。これは、その機能がXRデバイスで一部の構成でサポートされることが分かっている場合を意味します(たとえ現在の構成でサポートが確認できていなくとも)。ユーザー体験の一貫性向上のため、ユーザーエージェントはより厳格な制約を適用しても構いません。
注記:
例えば複数のVRデバイスは、ユーザーが移動できる安全な境界を設定する構成と、境界設定をスキップしユーザーがその場に立っていることを前提とする構成の両方をサポートします。このようなデバイスは、現時点で安全境界が構成されていなくても、体験がそれを必要とする場合ユーザーが適切に設定できると期待されるため、"bounded-floor"
XRReferenceSpace
のサポート可能とみなされます。これは、ユーザーエージェントがリクエスト機能の解決前にXRデバイスを完全に初期化したり、ユーザーの環境認識を待機せずに済むようにするためです。ただし、ユーザーエージェントがセッションリクエスト時に追加の初期化なしで境界状態を把握できるなら、安全境界が未設定の場合は"bounded-floor"
機能を拒否する選択もできます。
4. セッション
4.1. XRSession
XRハードウェアとのあらゆるやり取りは、XRSession
オブジェクトを通じて行われます。このオブジェクトはXRSystem
オブジェクトのrequestSession()
を呼び出すことでのみ取得できます。セッションの取得に成功した後は、ビューアの姿勢をポーリング
したり、ユーザーの環境に関する情報を問い合わせたり、画像をユーザーに提示するために利用できます。
ユーザーエージェントは、可能な限り、XRSession
が取得されるまで、デバイストラッキングやレンダリング機能を初期化すべきではありません。これは、XR機能を単に広告表示するためにXRハードウェアの存在をテストしたいだけのページに初めて移動したときなど、XRシステムが積極的に使用されていないのに副作用(バッテリー消費増加や関連ユーティリティアプリの表示など)が発生するのを防ぐためです。ただし、全てのXRプラットフォームがトラッキングの初期化なしにハードウェアの存在を検出できるわけではないため、これは強い推奨事項に留まります。
enum {
XRVisibilityState "visible" ,"visible-blurred" ,"hidden" , }; [SecureContext ,Exposed =Window ]interface :
XRSession EventTarget { // Attributesreadonly 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 ; // Methodsundefined 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 (); // Eventsattribute 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 ; };
各XRSession
は、mode(XRSessionMode
の値のいずれか)を持ちます。
各XRSession
は、アニメーションフレームを持ちます。これはactiveをfalse
、animationFrameをtrue
、session
をこのXRSession
に設定して初期化したXRFrame
です。
各XRSession
は、許可された機能のセットを持ちます。これはセットであり、DOMString
値として許可された機能記述子を表します。
enabledFeatures
属性は、許可された機能のセットに含まれる機能をDOMString
の新しい配列で返します。
isSystemKeyboardSupported
属性は、XRSystem
がXRSession
のアクティブ中にシステムキーボードを表示する機能を持つかどうかを示します。isSystemKeyboardSupported
がtrue
の場合、Web API(focusなど)でオーバーレイキーボードを呼び出すとシステムキーボードが表示されます。キーボードが表示されている間、XRSession
は"visible-blurred"
のvisibility stateを設定しなければなりません。
session, mode, granted, deviceを与えられたとき、ユーザーエージェントがセッションを初期化するには、次の手順を実行しなければなりません:
-
sessionのmodeをmodeに設定する。
-
sessionのXRデバイスをdeviceに設定する。
-
sessionの許可された機能のセットをgrantedに設定する。
-
レンダーステートを初期化する。
-
他のユーザーエージェントの機能がまだ実行していない場合は、デバイスのトラッキングおよびレンダリング機能を初期化するために必要なプラットフォーム固有の手順(ユーザーへの指示表示などを含む)を実行する。
注記: デバイスによっては起動時に追加のユーザー指示が必要な場合があります。例:スマートフォンベースのヘッドセットで没入モードに入るにはスマートフォンをヘッドセットに挿入する必要があり、デスクトップブラウザで外部ヘッドセットを利用する場合はヘッドセットを装着する必要があります。こうした指示を表示する責任は著者ではなくユーザーエージェントにあります。
さまざまな状況でセッションがシャットダウンされることがあります。これは恒久的かつ不可逆です。一度セッションがシャットダウンされると、XRデバイスのトラッキングやレンダリング機能を再び利用するには新たなセッションを取得する必要があります。各XRSession
は、endedブール値(初期値はfalse
)を持ち、シャットダウンされたかどうかを示します。
XRSession
sessionがシャットダウンされると、次の手順を実行します:
-
sessionのendedの値を
true
に設定する。 -
active immersive sessionがsessionと等しければ、active immersive sessionを
null
に設定する。 -
sessionをlist of inline sessionsから削除する。
-
Reject、sessionが返した未解決のpromiseを
InvalidStateError
で拒否する。ただしend()
が返したpromiseは除く。 -
他にユーザーエージェントの機能がそれらを積極的に使用していなければ、デバイスのトラッキングおよびレンダリング機能をシャットダウンするために必要なプラットフォーム固有の手順を実行する。これには必ず以下が含まれる:
-
sessionがimmersive sessionの場合、exclusive accessをXR deviceから解放すること。
-
sessionがXR deviceに対する描画のために取得したグラフィックスリソースを解放すること。
-
sessionがimmersive sessionの場合、XR deviceを他のソースが同じデバイスで新たなセッションを開始できる状態にすること。
-
-
タスクをキューし、session上で
XRSessionEvent
のend
という名前のイベントを発火する。
end()
メソッドはセッションを手動でシャットダウンする方法を提供します。呼び出されたとき、次の手順を実行しなければなりません:
-
promiseを、この
XRSession
の関連realmで新しいPromiseとする。 -
ended の値が
true
であれば、reject promiseを"InvalidStateError
"DOMException
で拒否し、promiseを返す。 -
セッションをシャットダウンする(this)。
-
タスクをキューして次の手順を実行する:
-
セッションのシャットダウンに関連するプラットフォーム固有の手順が完了するまで待機する。
-
resolve promise。
-
-
promiseを返す。
各XRSession
は、アクティブレンダーステート(新しいXRRenderState
)と、保留レンダーステート(初期値はnull
のXRRenderState
)を持ちます。
renderState
属性は、XRSession
のアクティブレンダーステートを返します。
各XRSession
は、最小インライン視野と最大インライン視野(ラジアン単位)を持ちます。値はユーザーエージェントが決定し、0
からPI
の範囲でなければなりません。
各XRSession
は、最小ニアクリップ面及び最大ファークリップ面(メートル単位)を持ちます。値はユーザーエージェントが決定し、非負でなければなりません。最小ニアクリップ面は0.1
未満が望ましく、最大ファークリップ面は1000.0
より大きい(または無限大)ことが望ましいです。
ユーザーエージェントがXRSession
sessionおよびXRRenderStateInit
newStateで保留レイヤーステートを更新する場合、次の手順を実行しなければなりません:
-
newStateの
layers
の値がnull
でない場合、NotSupportedError
をスローする。
注記: WebXR layers moduleがこのアルゴリズムに新しい意味づけを導入します。
ユーザーエージェントがXRSession
sessionにrateで名目フレームレートを適用したい場合、次の手順を実行しなければなりません:
-
rateがsessionの内部名目フレームレートと同じ場合、この手順を中止する。
-
sessionのended値が
true
の場合、この手順を中止する。 -
sessionの内部名目フレームレートをrateに設定する。
-
XRSessionEvent
イベント名frameratechange
をsessionに発火する。
updateTargetFrameRate(rate)
メソッドはXRSession
にターゲットフレームレートrateを伝えます。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionをthisとする。
-
promiseをsessionの関連realmで新しいPromiseとする。
-
sessionが内部名目フレームレートを持たない場合、reject promiseを"
InvalidStateError
"DOMException
で拒否し、promiseを返す。 -
sessionのended値が
true
の場合、reject promiseを"InvalidStateError
"DOMException
で拒否し、promiseを返す。 -
rateが
supportedFrameRates
に含まれていない場合、reject promiseを"TypeError
"DOMException
で拒否し、promiseを返す。 -
sessionの内部ターゲットフレームレートをrateに設定する。
-
タスクをキューして次の手順を実行する:
-
promiseを返す。
XRコンポジタが何らかの理由(例:"visible-blurred"
イベント中)で名目フレームレートを変更した場合、原因となったイベントが終了したら内部ターゲットフレームレートを使用するべきです。
updateRenderState(newState)
メソッドは、アクティブレンダーステートの更新をキューし、次のフレームで適用します。このメソッドに渡されたXRRenderStateInit
newStateの未設定フィールドは変更されません。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionをthisとする。
-
sessionのended値が
true
の場合、InvalidStateError
をスローし、この手順を中止する。 -
newStateの
baseLayer
がsession以外のXRSession
で作成された場合、InvalidStateError
をスローし、この手順を中止する。 -
newStateの
inlineVerticalFieldOfView
が設定されており、かつsessionが没入型セッションの場合、InvalidStateError
をスローし、この手順を中止する。 -
newStateの
depthNear
、depthFar
、inlineVerticalFieldOfView
、baseLayer
、layers
のいずれも設定されていなければ、この手順を中止する。 -
保留レイヤーステートを更新(session, newState)。
-
activeStateをsessionのアクティブレンダーステートとする。
-
sessionの保留レンダーステートが
null
の場合、activeStateのコピーで設定する。 -
newStateの
passthroughFullyObscured
が設定されていれば、sessionの保留レンダーステートのpassthroughFullyObscured
をnewStateの同名属性で設定する。 -
newStateの
depthNear
が設定されていれば、sessionの保留レンダーステートのdepthNear
をnewStateの同名属性で設定する。 -
newStateの
depthFar
が設定されていれば、sessionの保留レンダーステートのdepthFar
をnewStateの同名属性で設定する。 -
newStateの
inlineVerticalFieldOfView
が設定されていれば、sessionの保留レンダーステートのinlineVerticalFieldOfView
をnewStateの同名属性で設定する。 -
newStateの
baseLayer
が設定されていれば、sessionの保留レンダーステートのbaseLayer
をnewStateの同名属性で設定する。
要求された場合、XRSession
sessionは、次の手順を実行して保留中のレンダーステートを適用しなければなりません:
-
activeStateをsessionのアクティブレンダーステートとする。
-
newStateをsessionの保留レンダーステートとする。
-
sessionの保留レンダーステートを
null
に設定する。 -
oldBaseLayerをactiveStateの
baseLayer
とする。 -
oldLayersをactiveStateの
layers
とする。 -
タスクをキューして、次の手順を実行する:
-
activeStateをnewStateに設定する。
-
oldBaseLayerがactiveStateの
baseLayer
と等しくない、またはoldLayersがactiveStateのlayers
と等しくない、またはいずれかのレイヤーの寸法が変更された場合、ビューポートを更新する(session用)。 -
activeStateの
inlineVerticalFieldOfView
がsessionの最小インライン視野より小さい場合、activeStateのinlineVerticalFieldOfView
をsessionの最小インライン視野に設定する。 -
activeStateの
inlineVerticalFieldOfView
がsessionの最大インライン視野より大きい場合、activeStateのinlineVerticalFieldOfView
をsessionの最大インライン視野に設定する。 -
activeStateの
depthNear
がsessionの最小ニアクリップ面より小さい場合、activeStateのdepthNear
をsessionの最小ニアクリップ面に設定する。 -
activeStateの
depthFar
がsessionの最大ファークリップ面より大きい場合、activeStateのdepthFar
をsessionの最大ファークリップ面に設定する。 -
baseLayerをactiveStateの
baseLayer
とする。 -
activeStateのcomposition enabledおよびoutput canvasを以下のように設定する:
- sessionのmodeが
"inline"
であり、baseLayerがXRWebGLLayer
のインスタンスでcomposition enabledがfalse
の場合: -
activeStateのcomposition enabledブール値を
false
に設定する。activeStateのoutput canvasをbaseLayerのcontextの
canvas
に設定する。 - それ以外の場合:
-
activeStateのcomposition enabledブール値を
true
に設定する。activeStateのoutput canvasを
null
に設定する。
- sessionのmodeが
-
requestReferenceSpace(type)
メソッドは、可能であれば指定されたtypeのXRReferenceSpace
を構築します。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
promiseを、この
XRSession
の関連realmで新しいPromiseとする。 -
次の手順を並列で実行する:
-
reference space is supported(type, session)の結果が
false
の場合は、タスクをキューしてreject promiseをNotSupportedError
で拒否し、この手順を中止する。 -
type型のリファレンススペースをトラッキングするために必要なプラットフォームリソースをセットアップする。
ユーザーエージェントは、このようなリファレンススペースのトラッキングが確立されるのを待たずにrequestReferenceSpace()
を解決してよい。 セッションが最初にトラッキング確立を試みている間は、getViewerPose()
がnull
を返してもよいし、コンテンツはこの時間をスプラッシュ画面等の表示に利用できる。typeが"bounded-floor"
で、境界がまだ確立されていない場合、ユーザーエージェントは最初は小さなエリアを境界とし、境界が確定したらreset
イベントで通知してもよい。 -
タスクをキューして次の手順を実行する:
-
リファレンススペースを作成し、referenceSpaceとし、typeとsessionを設定する。
-
resolve promiseをreferenceSpaceで解決する。
-
-
promiseを返す。
各XRSession
は、アクティブなXR入力ソースのリスト(リスト(XRInputSource
))およびアクティブなXRトラッキングソースのリスト(リスト(XRInputSource
))を持ち、どちらも初期状態は空のリストでなければなりません。
各XRSession
は、初期化時に設定されるXRデバイス(XRデバイス)を持ちます。
inputSources
属性は、XRSession
のアクティブなXR入力ソースのリストを返します。
trackedSources
属性は、XRSession
のアクティブなXRトラッキングソースのリストを返します。
ユーザーエージェントは、XRデバイスに関連付けられたすべてのXR入力ソースを監視し、XR入力ソースが追加・削除・変更されたことを検知しなければなりません。
各XRSession
は、初期値false
のpromise resolvedフラグを持ちます。
注記: このフラグは、ユーザーコードが実際にイベントリスナーをアタッチできるようになるまで入力ソース追加・入力ソース削除・入力ソース変更アルゴリズムを実行しないためのものです。実装によっては、セッション解決後に入力ソースの監視を開始するだけでこのフラグは不要な場合もあります。
XRSession
sessionに対して新しいXR入力ソースが利用可能になる場合、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionのpromise resolvedフラグがセットされていなければ、この手順を中止する。
-
added primary sourcesを新しいリストとする。
-
added tracked sourcesを新しいリストとする。
-
各新しいXR入力ソースについて:
-
inputSourceを、この
XRSession
の関連realmで新しいXRInputSource
とし、次の分岐を行う:- inputSourceがプライマリ入力ソースの場合:
-
inputSourceをadded primary sourcesに追加する。
- それ以外の場合:
-
inputSourceをadded tracked sourcesに追加する。
-
-
タスクをキューして、次の手順を実行する:
-
拡張でsessionのアクティブなXR入力ソースのリストにadded primary sourcesを追加する。
-
added primary sourcesが空でない場合、
XRInputSourcesChangeEvent
イベント名inputsourceschange
を、sessionでadded
としてadded primary sourcesを指定して発火する。 -
拡張でsessionのアクティブなXRトラッキングソースのリストにadded tracked sourcesを追加する。
-
added tracked sourcesが空でない場合、
XRInputSourcesChangeEvent
イベント名trackedsourceschange
を、sessionでadded
としてadded tracked sourcesを指定して発火する。
-
これまでに追加されたXR入力ソースが利用できなくなった場合、XRSession
sessionについて、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionのpromise resolvedフラグが設定されていなければ、この手順を中止する。
-
removed primary sourcesを新しいリストとする。
-
removed tracked sourcesを新しいリストとする。
-
利用できなくなった各XR入力ソースについて:
-
inputSourceを、そのXR入力ソースに関連付けられたsessionのアクティブなXR入力ソースのリスト内の
XRInputSource
とし、次の分岐を行う:- inputSourceがプライマリ入力ソースの場合:
-
inputSourceをremoved primary sourcesに追加する。
- それ以外の場合:
-
inputSourceをremoved tracked sourcesに追加する。
-
-
タスクをキューして、以下の手順を実行する:
-
削除で、removed primary sources内の各
XRInputSource
をsessionのアクティブなXR入力ソースのリストから削除する。 -
removed primary sourcesが空でなければ、
XRInputSourcesChangeEvent
イベント名inputsourceschange
をsessionに対してremoved
にremoved primary sourcesを設定して発火する。 -
削除で、removed tracked sources内の各
XRInputSource
をsessionのアクティブなXRトラッキングソースのリストから削除する。 -
removed tracked sourcesが空でなければ、
XRInputSourcesChangeEvent
イベント名trackedsourceschange
をsessionに対してremoved
にremoved tracked sourcesを設定して発火する。
-
注記: ユーザーエージェントは、入力ソースが一時的に位置・姿勢トラッキングを両方とも失ったとき、このイベントを発火してもよいです。これは物理的なハンドヘルドコントローラー入力ソースにのみ推奨されます。トラッキングハンド入力ソースでは頻繁に発生するため、このイベントを発火するのは推奨されません。また、トラッカーオブジェクト入力ソースの場合も、アプリケーションが識別性を維持しにくくなるため推奨されません。
handedness
、
targetRayMode
、
profiles
、
gripSpace
の有無、
またはプライマリ入力ソースかトラッキング入力ソースかのステータスが
XR入力ソースで変化した場合、XRSession
sessionについて、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionのpromise resolvedフラグが設定されていなければ、この手順を中止する。
-
added primary sourcesを新しいリストとする。
-
removed primary sourcesを新しいリストとする。
-
added tracked sourcesを新しいリストとする。
-
removed tracked sourcesを新しいリストとする。
-
変更された各XR入力ソースについて:
-
oldInputSourceを、そのXR入力ソースに以前関連付けられていたsessionのアクティブなXR入力ソースのリスト内の
XRInputSource
とし、次の分岐を行う:- oldInputSourceがプライマリ入力ソースであるか、またはその状態がプライマリ入力ソースからトラッキング入力ソースに変化した場合:
-
oldInputSourceをremoved primary sourcesに追加する。
- それ以外の場合:
-
oldInputSourceをremoved tracked sourcesに追加する。
-
newInputSourceを、sessionの関連realmで新しい
XRInputSource
とし、次の分岐を行う:- newInputSourceがプライマリ入力ソースであるか、またはその状態がトラッキング入力ソースからプライマリ入力ソースに変化した場合:
-
newInputSourceをadded primary sourcesに追加する。
- それ以外の場合:
-
newInputSourceをadded tracked sourcesに追加する。
-
-
タスクをキューして、以下の手順を実行する:
-
削除で、removed primary sources内の
XRInputSource
をsessionのアクティブなXR入力ソースのリストから削除する。 -
拡張でsessionのアクティブなXR入力ソースのリストにadded primary sourcesを追加する。
-
added primary sourcesまたはremoved primary sourcesが空でなければ、
XRInputSourcesChangeEvent
イベント名inputsourceschange
をsessionに対してadded
にadded primary sources、removed
にremoved primary sourcesを設定して発火する。 -
削除で、removed tracked sources内の
XRInputSource
をsessionのアクティブなXRトラッキングソースのリストから削除する。 -
拡張でsessionのアクティブなXR入力ソースのリストにadded tracked sourcesを追加する。
-
added tracked sourcesまたはremoved tracked sourcesが空でなければ、
XRInputSourcesChangeEvent
イベント名trackedsourceschange
をsessionに対してadded
にadded tracked sources、removed
にremoved tracked sourcesを設定して発火する。
-
XRSession
ごとにvisibility state値(enum)がある。インラインセッションの場合、visibility stateはDocument
のvisibilityStateを反映しなければならない。没入型セッションの場合、visibility
stateは次のいずれか、そのセッション状態に最も合致する値に設定しなければならない。
-
visible
状態は、XRSession
で描画された画像がユーザーに見えており、requestAnimationFrame()
コールバックがXRデバイスのネイティブリフレッシュレートで処理されることを示します。入力も通常通りXRSession
で処理されます。 -
visible-blurred
状態は、XRSession
で描画された画像がユーザーに見えている可能性があるが主フォーカスでないことを示します。requestAnimationFrame()
コールバックはスロットルされる場合があります。入力はXRSession
で処理されません。 -
hidden
状態は、XRSession
で描画された画像がユーザーに全く見えないことを示します。requestAnimationFrame()
コールバックはvisibility stateが変化するまで処理されません。入力はXRSession
で処理されません。
visibilityState
属性は、XRSession
のvisibility stateを返します。onvisibilitychange
属性は、イベントハンドラーIDL属性であり、visibilitychange
イベントタイプ用です。
visibility stateは、XRアニメーションフレームの処理中以外の任意のタイミングでユーザーエージェントにより変更されてもよく、可能な場合ユーザーエージェントはXRプラットフォームを監視してセッションの可視性が外部要因で変化した場合にvisibility stateを更新すべきです。
注記: XRSession
のvisibility
stateは、必ずしもHTMLドキュメントの可視性を意味するものではありません。システム構成によっては、イマーシブセッションがアクティブな間もページが引き続き表示される場合があります。(例えば、PCに接続されたヘッドセットでは、ヘッドセットでイマーシブセッションのコンテンツが表示されている間も、モニター上にページが表示され続けることがあります。)開発者はページの可視性の判定には引き続きPage
Visibilityを利用してください。
注記: XRSession
のvisibility stateは、没入型セッションがアクティブな間も2Dコンテンツが表示されているテザードセッションでマウス動作には影響・制限を与えません。マウスの挙動をより厳密に制御したい場合は[pointerlock]
APIの利用を検討してください。
XRSystem
では、フレームレートを表す定義がいくつかあります:
-
名目フレームレート:
XRSystem
が名目パフォーマンス維持のため体験にレンダリングを要求するレート。フレームを落とすとrequestAnimationFrame()
のコール数がこの値より少なくなる場合がありますが、XRSystem
はこの値を目指します。 -
実効フレームレート:実際に体験が1秒間に処理できた
requestAnimationFrame()
の回数。XRSystem
のフレームタイミングに間に合うかどうかで変動します。 -
ターゲットフレームレート:体験側が
XRSystem
に希望する名目フレームレートのヒント。 -
表示フレームレート:物理ディスプレイにフレームが描画される実レート。体験の名目フレームレートから導出される場合がありますが、ハードウェア実装依存で体験側には公開されません。
XRSession
はターゲットフレームレートとなる内部ターゲットフレームレートを持つ場合があります。
XRSession
は名目フレームレートとなる内部名目フレームレートを持つ場合があります。実効フレームレートが名目フレームレートより低い場合、XRコンポジタがリプロジェクション等で体験を改善する場合があります。これはオプションであり、inline
セッションでは存在してはなりません。
frameRate
属性は内部名目フレームレートを反映します。XRSession
が内部名目フレームレートを持たない場合はnull
を返します。
onframeratechange
属性は、イベントハンドラーIDL属性であり、frameratechange
イベントタイプ用です。XRSession
の名目フレームレートが何らかの理由で変更された場合、新しい名目フレームレートとともに名目フレームレートを適用しなければなりません。
supportedFrameRates
属性は、サポートされるターゲットフレームレート値のリストを返します。この属性はオプションであり、inline
セッションやフレームレートの制御を著者に許可しないXRSystem
では存在してはなりません。XRSession
がsupportedFrameRates
属性をサポートする場合、frameRate
もサポートしなければなりません。
XRSession
ごとに、型XRReferenceSpace
で"viewer"
かつ単位変換のorigin
offsetをもつビューアリファレンススペースがある。
XRSession
ごとにリストでviewに対応したビューリストがあり、XRデバイスが提供するビューに対応します。XRSession
のrenderState
のcomposition enabledブール値がfalse
の場合、ビューリストは単一のviewのみを含まなければなりません。ビューリストはXRSession
中は不変であり、セッション中に現れる可能性のあるすべてのview(初期状態でactiveでない副ビューを含む)を含まなければなりません。
onend
属性は、イベントハンドラーIDL属性であり、end
イベントタイプ用です。
oninputsourceschange
属性は、イベントハンドラーIDL属性であり、inputsourceschange
イベントタイプ用です。
onselectstart
属性は、イベントハンドラーIDL属性であり、selectstart
イベントタイプ用です。
onselectend
属性は、イベントハンドラーIDL属性であり、selectend
イベントタイプ用です。
onselect
属性は、イベントハンドラーIDL属性であり、select
イベントタイプ用です。
onsqueezestart
属性は、イベントハンドラーIDL属性であり、squeezestart
イベントタイプ用です。
onsqueezeend
属性は、イベントハンドラーIDL属性であり、squeezeend
イベントタイプ用です。
onsqueeze
属性は、イベントハンドラーIDL属性であり、squeeze
イベントタイプ用です。
4.2. XRRenderState
XRRenderState
は、XRSession
の出力がどのように合成されるかに影響する、設定可能な値のセットを表します。ある XRSession
の アクティブレンダーステート
はフレームの境界間のみ変更でき、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 ; };
各 XRRenderState
は 出力キャンバス を持ちます。これは HTMLCanvasElement
であり、初期値は null
です。出力キャンバス は、"inline"
XRSession
の描画コンテンツを表示するDOM要素です。
各 XRRenderState
は composition enabled ブール値を持ち、初期値は true
です。XRRenderState
が composition enabled
の場合、APIが提供するサーフェスに対してレンダリングコマンドが実行され、その結果が XRコンポジタ によって表示されます。もし "inline"
XRSession
で直接 出力キャンバス に描画される場合、その XRRenderState
の composition enabled フラグは false
でなければなりません。
注記: この段階では XRRenderState
は composition enabled が false
の場合にのみ 出力キャンバス を持ちますが、将来の仕様ではミラーやレイヤー合成など、composition
を要する高度な用途のため 出力キャンバス を設定するメソッドが導入される可能性があります。
XRRenderState
オブジェクトが XRSession
session のために作成されるとき、ユーザーエージェントは次の手順で レンダーステートを初期化 しなければなりません:
-
state を session の 関連realm で 新しい
XRRenderState
オブジェクトとする。 -
state の
depthNear
を0.1
に初期化する。 -
state の
depthFar
を1000.0
に初期化する。 -
state の
passthroughFullyObscured
をfalse
に初期化する。 -
state の
inlineVerticalFieldOfView
を以下のように初期化する:- session が インラインセッション の場合:
-
state の
inlineVerticalFieldOfView
をPI * 0.5
に初期化する。 - それ以外の場合:
-
state の
inlineVerticalFieldOfView
をnull
に初期化する。
-
state の
baseLayer
をnull
に初期化する。
depthNear
属性は、viewer からのニアクリップ面までの距離(メートル)を定義します。depthFar
属性は、viewer からのファークリップ面までの距離(メートル)を定義します。
depthNear
と depthFar
は projectionMatrix
(XRView
)の計算に使われます。描画時に
projectionMatrix
が使われるとき、viewer からの距離が depthNear
以上 depthFar
以下でない限りジオメトリは描画されません。また XRWebGLLayer
のデプスバッファ値の解釈にも影響します。depthNear
は depthFar
より大きくても構いません。
注記: 通常パースペクティブ投影行列を構築する際、開発者は視錐台とニア・ファークリップ面を指定します。没入型XRデバイス への表示時は、正しい視錐台は光学系やディスプレイ、カメラ等の組み合わせで決まりますが、クリップ面の値はレンダリングするコンテンツの種類によって適切な値が変わるため、アプリケーション側で変更できます。
passthroughFullyObscured
属性は、著者がビューポート全体を仮想コンテンツで完全に覆う意図があることを XRSystem
に伝えるヒントです。ビューポートが不透明ピクセルで覆われなくなったら、このフラグを false
に戻すべきです。
注記: XRSystem
はこれをヒントに一時的にパススルーを無効化することがあります。シースルー光学デバイスではユーザーは実環境を見続けるため、このフラグに効果はありません。
inlineVerticalFieldOfView
属性は、"inline"
XRSession
の投影行列計算時に使われるデフォルトの縦視野(ラジアン単位)を定義します。投影行列の計算では 出力キャンバス のアスペクト比も考慮されます。この値は 没入型セッション では必ず null
でなければなりません。
baseLayer
属性は、XRコンポジタ が画像を取得する XRWebGLLayer
を定義します。
4.3. アニメーションフレーム
XRSession
がXRデバイスのトラッキング状態に関する情報を提供する主な方法は、XRSession
インスタンスでrequestAnimationFrame()
を呼び出してスケジュールされたコールバックを通じて行われます。
callback =
XRFrameRequestCallback undefined (DOMHighResTimeStamp ,
time XRFrame );
frame
各XRFrameRequestCallback
オブジェクトは、初期値false
のcancelledブール値を持ちます。
各XRSession
は、
初期状態で空のアニメーションフレームコールバックのリスト、
同じく空の実行中アニメーションフレームコールバックのリスト、
さらに初期値0のアニメーションフレームコールバック識別子(数値)を持ちます。
requestAnimationFrame(callback)
メソッドは、ユーザーエージェントが次にデバイス用のアニメーションフレームを実行したいときにcallbackが実行されるようキューします。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionをthisとする。
-
sessionのended値が
true
の場合、0
を返してこの手順を中止する。 -
sessionのアニメーションフレームコールバック識別子を1増やす。
-
callbackを、現在のアニメーションフレームコールバック識別子の値と関連付けてsessionのアニメーションフレームコールバックのリストに追加する。
-
sessionのアニメーションフレームコールバック識別子の現在値を返す。
cancelAnimationFrame(handle)
メソッドは、アニメーションフレームコールバック識別子handleで指定された既存のアニメーションフレームコールバックをキャンセルします。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionをthisとする。
-
sessionのanimation frame callbacks のリストまたは sessionの現在実行中の animation frame callbacks のリストの中で、値handleに関連付けられたエントリを探す。
-
そのようなエントリが存在する場合、そのcancelledブール値を
true
に設定し、sessionのanimation frame callbacks のリストから削除する。
renderState
stateについて、ユーザーエージェントは次の手順を実行しなければなりません:
-
stateの
baseLayer
がnull
であればfalse
を返す。 -
true
を返す。
注記: WebXR layers moduleはこのアルゴリズムに新たな意味を導入します。
XRSession
sessionについて判定するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionの
renderState
で レイヤーステートを確認がfalse
ならfalse
を返す。 -
sessionのmodeが
"inline"
であり、 かつsessionのrenderState
の output canvasがnull
ならfalse
を返す。 -
true
を返す。
XRSession
sessionがviewer状態の更新(タイムスタンプframeTime)をXRデバイスから受け取ったとき、XRアニメーションフレームを実行し、アニメーションフレームコールバックのリストが空かどうかに関わらず次の手順を必ず実行する:
-
タスクをキューして次の手順を実行:
-
nowを現在の高精度時刻とする。
-
frameをsessionのアニメーションフレームとする。
-
frameのtimeをframeTimeに設定する。
-
frameの
predictedDisplayTime
をframeTimeに設定する。 -
sessionのmodeが
"inline"
でない場合、 frameのpredictedDisplayTime
をXRコンポジタがこのXRアニメーションフレームを表示する平均タイムスタンプに設定する。 -
ビューリスト内の各viewについて、viewのviewport modifiableフラグをtrueにする。
-
前回のXRアニメーションフレーム以降で ビューリスト内のいずれかのviewのactiveフラグが変化していたら、 ビューポートを更新する。
-
このフレームが描画されるべき場合:
-
sessionの実行中アニメーションフレームコールバックのリストを sessionのアニメーションフレームコールバックのリストにする。
-
sessionのアニメーションフレームコールバックのリストを空リストにする。
-
frameのactiveブール値を
true
にする。 -
フレーム更新を適用する(frame)。
-
sessionの実行中アニメーションフレームコールバックのリストの各entryについて、順に:
-
entryのcancelledブール値が
true
なら次のentryへ。 -
コールバック関数を呼び出す(entry, «now, frame», "
report
")。 -
sessionの実行中アニメーションフレームコールバックのリストを空リストにする。
-
frameのactiveブール値を
false
にする。
-
-
sessionの保留レンダーステートが
null
でなければ、保留レンダーステートを適用する。
-
Window
インターフェイスのrequestAnimationFrame()
メソッドは、アクティブなXRSession
が存在するかどうかによって動作が変わることはなく、requestAnimationFrame()
をXRSession
上で呼び出してもWindow
の
requestAnimationFrame()
とは相互作用しません。アクティブな没入型セッションは、ページが隠されている場合に
レンダリング機会
に影響を与えることがあります。2Dブラウザビューがアクティブな没入型セッション
中も可視な場合(例:テザードヘッドセット)、Window
の
requestAnimationFrame()
やrequestIdleCallback()
のコールバックのタイミングは、セッションのrequestAnimationFrame()
とは一致しない場合があり、ユーザーはXRコンテンツのレンダリングのためにそれに依存すべきではありません。
注記: XRSession
の
requestAnimationFrame()
がWindow
の
requestAnimationFrame()
でスケジュールされたコールバック中に呼び出された場合、ユーザーエージェントは開発者コンソールに警告を表示したいかもしれません。なぜならアクティブな没入型セッション
が
レンダリング機会
に影響を与えると、これらのコールバックは発生しない保証がなく、発生しても正しいタイミングではないためです。
Window
のrequestAnimationFrame()
に渡したコールバックはセッション中に処理されないことがあります。これは利用するデバイスの種類に依存し、特にモバイルやスタンドアロンデバイスのように没入コンテンツがHTMLドキュメントを完全に覆い隠す場合に発生しやすいです。そのため、開発者はWindow
のrequestAnimationFrame()
コールバックでXRSession
のrequestAnimationFrame()
コールバックをスケジュールしたり、その逆をしたりしてはいけません。たとえ描画ロジックを共有していてもです。このガイダンスに従わないアプリケーションは、すべてのプラットフォームで正しく動作しない場合があります。2種類のアニメーションループを切り替えたいアプリケーションのより効果的なパターン例を以下に示します:
let xrSession= null ; function onWindowAnimationFrame( time) { window. requestAnimationFrame( onWindowAnimationFrame); // 没入セッションが一部デバイス(例: テザードヘッドセットのデスクトップなど)で実行中にも呼ばれることがあります。 // 2つのループが並行描画しないよう、セッション終了までここでの描画をスキップします。 if ( ! xrSession) { renderFrame( time, null ); } } // windowアニメーションループはページロード直後から開始できる。 window. requestAnimationFrame( onWindowAnimationFrame); function onXRAnimationFrame( time, xrFrame) { xrSession. requestAnimationFrame( onXRAnimationFrame); renderFrame( xrFrame. predictedDisplayTime, xrFrame); } function renderFrame( time, xrFrame) { // 共通描画処理 } // 他のユーザー操作イベントから呼ばれると仮定。 async function startXRSession() { xrSession= await navigator. xr. requestSession( 'immersive-vr' ); xrSession. addEventListener( 'end' , onXRSessionEnded); // 必要なセッションセットアップ処理 // セッションのアニメーションループを開始 xrSession. requestAnimationFrame( onXRAnimationFrame); } function onXRSessionEnded() { xrSession= null ; }
"inline"
セッションでHTMLドキュメント描画を行う場合、特別なアニメーションループ調整は不要です。ユーザーエージェントが"inline"
セッションのアニメーションループを、没入型セッションがアクティブな間は自動的に中断します。
4.4. XRコンポジタ
ユーザーエージェントは、XRコンポジタを維持しなければなりません。これはXRデバイスへの表示やフレームタイミングを担当します。コンポジタはドキュメントが作成したグラフィックスコンテキストとは独立したレンダリングコンテキストを用い、その状態は分離されなければなりません。コンポジタはページが他のページやアプリケーションの内容を破壊したり読み取ったりできないようにしなければなりません。さらに、ページのパフォーマンスとユーザーへの新しい画像表示能力を適切なフレームレートで切り離すため、コンポジタは別スレッドまたはプロセスで動作しなければなりません。コンポジタはデバイスメニューなどの追加のデバイスまたはユーザーエージェントUIを描画コンテンツ上に合成してもかまいません。
注記: この仕様の将来の拡張では、同一ページからの複数レイヤーの合成にもコンポジタを利用する可能性があります。
5. フレームループ
5.1. XRFrame
XRFrame
は、XRSession
におけるすべてのトラッキング対象オブジェクトの状態のスナップショットを表します。アプリケーションはXRSession
でrequestAnimationFrame()
を呼び出し、XRFrameRequestCallback
により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
を返します。
没入型セッションの場合、predictedDisplayTime
属性は、このXRFrame
がデバイスのディスプレイに表示されると予想される平均時刻に対応するDOMHighResTimeStamp
を返さなければなりません。"inline"
XRSession
の場合、predictedDisplayTime
はXRFrameRequestCallback
に渡されたタイムスタンプと同じ値を返さなければなりません。
predictedDisplayTime
は、フレームが表示される時点でアニメーションされたXRシーンの状態を描画できるようにすることを目的としています。これは、requestAnimationFrame()
のコールバックがスケジュールされた時や実行された時点ではありません。
predictedDisplayTime
は、アプリケーションがレンダリングに使える残り時間を推測するためのものではありません。XRコンポジタは通常、フレーム提出後に追加処理を行う必要があります。predictedDisplayTime
まで処理できると仮定すると、XRコンポジタは提出フレームを利用できず、アプリケーションは目標フレームレートを維持できません。
各XRFrame
は、ある時刻におけるすべてのトラッキング対象オブジェクトの状態を表し、その時刻の状態について具体的な情報を格納または問い合わせできます。
getViewerPose(referenceSpace)
メソッドは、XRFrame
の時刻におけるreferenceSpaceに対するviewerの姿勢をXRViewerPose
として返します。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
frameをthisとする。
-
sessionをframeの
session
オブジェクトとする。 -
frameのanimationFrameブール値が
false
なら、InvalidStateError
をスローし手順を中止する。 -
poseをsessionの関連realmで新しい
XRViewerPose
オブジェクトとする。 -
populate the poseをsessionのviewer reference spaceとreferenceSpace、frameの表す時刻、force emulation =
true
でposeに適用する。 -
poseが
null
ならnull
を返す。 -
xrviewsを空のリストとする。
-
offset を
0
とする。 -
active な view view を
session
の list of views から 1つずつ取り出し、以下の手順を実行する:-
xrview を session の relevant realm における新しい
XRView
オブジェクトとする。 -
xrview の underlying view を view に初期化する。
-
xrview の
index
を offset に初期化する。 -
xrview の frame を frame に初期化する。
-
xrview の session を session に初期化する。
-
xrview の reference space を referenceSpace に初期化する。
-
viewtransform を session の relevant realm における view offset と等しい 新しい
XRRigidTransform
オブジェクトとする。 -
xrview の
transform
プロパティを、XRViewerPose
のtransform
と viewtransform transform を 乗算した結果(session の relevant realm で)に設定する。 -
Append で xrview を xrviews に追加する。
-
offset を
1
増やす。
-
-
poseの
views
をxrviewsに設定する。 -
poseを返す。
getPose(space, baseSpace)
メソッドは、XRFrame
の時刻におけるbaseSpaceに対するspaceの姿勢をXRPose
として返します。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
frameをthisとする。
-
populate the poseをspaceとbaseSpace、frameの時刻でposeに適用する。
-
poseを返す。
フレームアップデートは、XRFrame
を与えて実行されるアルゴリズムであり、各XRFrame
ごとに実行されることを意図しています。
すべてのXRSession
はフレームアップデートのリスト(リスト)を持ち、初期状態は空のリストです。
あるXRFrame
frameに対してフレームアップデートを適用するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
frameの
session
のフレームアップデートのリスト内の各frame updateについて、次を実行:-
frame updateをframeで実行する。
-
注記: 本仕様ではフレームアップデートは定義されていませんが、他の仕様で追加される場合があります。
6. Space(空間)
WebXR Device APIのコア機能の一つは空間トラッキングを提供できることです。Spaceは、アプリケーションがトラッキングされる実体同士やユーザーの物理環境との空間的関係を解釈するためのインターフェイスです。
6.1. XRSpace
XRSpace
は、物理的な位置に対応した原点を持つ仮想座標系を表します。APIから要求またはAPIに提供される空間データは、必ず特定のXRSpace
および特定のXRFrame
で定義される時点に対する関係として表現されます。姿勢の座標値などの数値は、そのspaceの原点を基準とした座標です。このインターフェイスは意図的に不透明に設計されています。
[SecureContext ,Exposed =Window ]interface :
XRSpace EventTarget { };
各XRSpace
は、
そのXRSpace
を作成したXRSession
に設定されるsessionを持ちます。
各XRSpace
は、
空間内の位置と姿勢を表すネイティブ原点を持ちます。XRSpace
のネイティブ原点はXRデバイスの基盤となるトラッキングシステムによって更新される場合があり、異なるXRSpace
はそのネイティブ原点がどのようにトラッキング・更新されるかに異なる意味付けを持ちます。
各XRSpace
は、
有効原点を持ち、これはXRSpace
の座標系の基準となります。
有効spaceからネイティブ原点空間への変換は、原点オフセットで定義されます。これは初期値が単位変換のXRRigidTransform
です。つまり有効原点は原点オフセットとネイティブ原点を乗算することで得られます。
XRSpace
の有効原点は、他のXRSpace
の座標系内でのみ、XRPose
として観測できます。これはXRFrame
のgetPose()
メソッドで返されます。XRSpace
同士の空間関係はXRFrame
ごとに変化する場合があります。
populate the
poseとは、XRSpace
のspaceを、XRSpace
のbaseSpaceにおいて、XRFrame
のframeで示される時点の、
XRPose
のposeに対して、オプションでforce
emulationフラグを指定して、次の手順をユーザーエージェントが実行しなければならないことを指す。
-
frameのactiveブール値が
false
なら、InvalidStateError
をスローして中止。 -
sessionをframeの
session
とする。 -
spaceのsessionがsessionでなければ、
InvalidStateError
をスローして中止。 -
baseSpaceのsessionがsessionでなければ、
InvalidStateError
をスローして中止。 -
姿勢が報告可能かを判定し、不可なら
SecurityError
をスローして中止。 -
sessionの
visibilityState
が"visible-blurred"
で、かつspaceまたはbaseSpaceがXRInputSource
に関連付けられている場合、poseをnull
にして中止。 -
limitにspaceとbaseSpace間で姿勢制限が必要かの判定結果を設定。
-
transformをposeの
transform
とする。 -
XRデバイスのトラッキングシステムに、frameの時刻におけるspaceのbaseSpaceに対する姿勢の問い合わせを行い、次の分岐を実行:
-
limitが
false
で、トラッキングシステムがspaceのbaseSpaceに対する6DoFの位置が積極的にトラッキングまたは静的に既知である場合: -
transformの
orientation
を、baseSpaceの座標系内でのspaceの有効原点の向きに設定。transformの
position
を、baseSpaceの座標系内でのspaceの有効原点の位置に設定。サポートされていれば、poseの
linearVelocity
を、baseSpaceの座標系に対するspaceの有効原点の線形速度に設定。サポートされていれば、poseの
angularVelocity
を、baseSpaceの座標系に対するspaceの有効原点の角速度に設定。poseの
emulatedPosition
をfalse
に設定。 -
それ以外でlimitが
false
かつ3DoFまたは6DoFだが位置が積極的にトラッキングされていない/静的に既知でない場合: -
transformの
orientation
を、baseSpaceの座標系内でのspaceの有効原点の向きに設定。transformの
position
を、baseSpaceの座標系内でのspaceの有効原点の位置の推定値に設定。これは首や腕モデルなどのオフセットを含む場合がある。位置推定がなければ直前の既知位置を使う。poseの
linearVelocity
をnull
に設定。poseの
angularVelocity
をnull
に設定。poseの
emulatedPosition
をtrue
に設定。 - さらに、spaceのbaseSpaceに対する姿勢が過去に確定していて、force
emulationが
true
の場合: -
transformの
position
を、baseSpaceの座標系内でのspaceの有効原点の直前の既知位置に設定。transformの
orientation
を、baseSpaceの座標系内でのspaceの有効原点の直前の既知向きに設定。poseの
linearVelocity
をnull
に設定。poseの
angularVelocity
をnull
に設定。poseの
emulatedPosition
をtrue
に設定。 - それ以外の場合:
-
poseを
null
に設定。
-
limitが
注記: XRPose
のemulatedPosition
ブール値は、baseSpaceの位置がエミュレートかどうかを示すものではなく、あくまでspaceのbaseSpaceに対する位置評価がエミュレーションに依存しているかどうかのみを示します。例えば3DoFトラッキングのコントローラーでtargetRaySpace
やgripSpace
をXRReferenceSpace
に対して問い合わせるとemulatedPosition
はtrue
になりますが、targetRaySpace
をgripSpace
に対して問い合わせた場合、その関係は正確に分かっているはずなのでemulatedPosition
はfalse
となります。
6.2. XRReferenceSpace
XRReferenceSpace
は、アプリケーションがユーザーの物理環境との空間的関係を確立するために利用できる、いくつかの共通XRSpace
の1つです。
XRReferenceSpace
は通常、XRSession
の間は静的であることが期待されていますが、最も一般的な例外はユーザーによるセッション途中の再設定です。すべてのXRReferenceSpace
のネイティブ原点は、+X
が「右」、+Y
が「上」、-Z
が「前方」とみなされる座標系を記述します。
enum {
XRReferenceSpaceType "viewer" ,"local" ,"local-floor" ,"bounded-floor" ,"unbounded" }; [SecureContext ,Exposed =Window ]interface :
XRReferenceSpace XRSpace { [NewObject ]XRReferenceSpace getOffsetReferenceSpace (XRRigidTransform );
originOffset attribute EventHandler onreset ; };
各XRReferenceSpace
は、type(XRReferenceSpaceType
)を持ちます。
XRReferenceSpace
は、通常requestReferenceSpace()
を呼び出して取得されます。これは、渡されたXRReferenceSpaceType
のenum値がサポートされている場合、XRReferenceSpace
(またはその拡張インターフェイス)のインスタンスを生成します。typeはそのリファレンススペースのトラッキングの挙動を示します:
-
viewer
を指定すると、XRReferenceSpace
のインスタンスが作成されます。これはネイティブ原点がviewerの位置と姿勢をトラッキングする空間を表します。すべてのXRSession
は"viewer"
XRReferenceSpace
をサポートしなければなりません。 -
local
を指定すると、XRReferenceSpace
のインスタンスが作成されます。これは生成時のviewerの近くをネイティブ原点とするトラッキング空間です。正確な位置や姿勢は基盤プラットフォームの慣例により初期化されます。このリファレンススペースではユーザーは初期位置から大きく動かない前提で、トラッキングもそれに最適化されています。6DoFトラッキング対応デバイスでは、local
リファレンススペースはユーザー環境に対する原点の安定性を重視すべきです。 -
local-floor
を指定すると、XRReferenceSpace
のインスタンスが作成されます。これはユーザーが安全に立てる床位置をネイティブ原点とするトラッキング空間です。Y軸=0が床レベルとなり、X軸/Z軸の位置や姿勢は基盤プラットフォームの慣例で初期化されます。床レベルが不明な場合は推定床レベルとし、非デフォルト値の場合はフィンガープリント防止のため十分に丸めなければなりません。このリファレンススペースでもユーザーは初期位置から大きく動かない前提で、トラッキングも最適化されます。6DoFトラッキング対応デバイスではlocal-floor
リファレンススペースもユーザー環境に対する原点の安定性を重視すべきです。注記:
"local-floor"
リファレンススペースの床レベルをフィンガープリント防止のため調整する場合、1cm単位で丸めることが推奨されます。 -
bounded-floor
を指定すると、XRBoundedReferenceSpace
のインスタンスが作成されます。これは床をネイティブ原点とし、ユーザーがboundsGeometry
で与えられる事前に定められた境界内で移動することを想定したトラッキング空間です。bounded-floor
リファレンススペースでは、ネイティブ原点やboundsGeometry
のユーザー環境に対する安定性を重視してトラッキングされます。 -
unbounded
を指定すると、XRReferenceSpace
のインスタンスが作成されます。これはユーザーが開始位置から離れて自由に環境内を移動することを想定したトラッキング空間です。unbounded
リファレンススペースでは、ユーザーの現在位置周辺での安定性を重視してトラッキングされるため、ネイティブ原点が時間とともにドリフトする場合があります。
注記: 基盤プラットフォームのリファレンススペースのY軸に関する慣例は、異なるXRReferenceSpace
タイプ間でも一貫していると想定されています。つまり、複数のリファレンススペースをサポートするXRシステムでは、それらのY軸は互いに平行で同じ方向を向き、同じXRSession
の間は維持されます。ただし"viewer"
は基盤プラットフォームの慣例に依存しません。"unbounded"
リファレンススペースは、原点が近い場合は他のリファレンススペースとY軸を揃えるべきですが、ユーザーが大きく動いた場合はずれることがあります。
"local"
リファレンススペースをサポートするデバイスは、"local-floor"
リファレンススペースも(必要ならエミュレーションで)サポートしなければなりませんし、その逆も同様です。
onreset
属性は、イベントハンドラーIDL属性であり、reset
イベントタイプ用です。
XRReferenceSpace
がXRReferenceSpaceType
typeでXRSession
session用に要求されたとき、ユーザーエージェントは次の手順でリファレンススペースを作成しなければなりません:
-
referenceSpaceを次のように初期化する:
- typeが
bounded-floor
の場合: -
referenceSpaceをsessionの関連realmで新しい
XRBoundedReferenceSpace
とする。 - それ以外の場合:
-
referenceSpaceをsessionの関連realmで新しい
XRReferenceSpace
とする。
- typeが
-
referenceSpaceのtypeをtypeに初期化する。
-
referenceSpaceのsessionをsessionに初期化する。
-
referenceSpaceを返す。
XRSession
sessionについて、次の手順を実行する:
-
typeがsessionの許可された機能のセットに含まれていない場合、
false
を返す。 -
typeが
viewer
の場合、true
を返す。 -
typeが
local
またはlocal-floor
で、sessionが没入型セッションの場合、true
を返す。 -
typeが
local
またはlocal-floor
で、XRデバイスが方位データの報告をサポートしている場合、true
を返す。 -
typeが
bounded-floor
で、sessionが没入型セッションの場合、境界付きリファレンススペースがサポートされているかをsessionのXRデバイスで判定してその結果を返す。 -
typeが
unbounded
で、sessionが没入型セッションかつ、XRデバイスがユーザー近傍で無制限距離の安定トラッキングをサポートしていれば、true
を返す。 -
false
を返す。
getOffsetReferenceSpace(originOffset)
メソッドが呼び出されたとき、必ず次の手順を実行しなければなりません:
-
baseをこのメソッドが呼ばれた
XRReferenceSpace
とする。 -
offsetSpaceを次のように初期化する:
- baseが
XRBoundedReferenceSpace
のインスタンスの場合: -
offsetSpaceをbaseの関連realmで新しい
XRBoundedReferenceSpace
とし、offsetSpaceのboundsGeometry
をbaseのboundsGeometry
に設定し、各点にoriginOffsetのinverse
を乗算する。 - それ以外の場合:
-
offsetSpaceをbaseの関連realmで新しい
XRReferenceSpace
とする。
- baseが
-
offsetSpaceの原点オフセットを、baseの原点オフセットにoriginOffsetを乗算した結果で更新する(baseの関連realm)。
-
offsetSpaceを返す。
注記: 一部のアプリケーションはgetOffsetReferenceSpace()
を利用して、マウス・キーボード・タッチ・ゲームパッド入力によるシーンナビゲーション制御を実装することが想定されています。その場合、入力がアクティブな間は少なくとも1フレームごとにgetOffsetReferenceSpace()
が頻繁に呼ばれます。したがってUAはgetOffsetReferenceSpace()
による新しいXRReferenceSpace
の作成を軽量な処理とするよう強く推奨されます。
6.3. XRBoundedReferenceSpace
XRBoundedReferenceSpace
は XRReferenceSpace
を拡張し、boundsGeometry
(ユーザーの空間の事前構成境界)を含みます。
[SecureContext ,Exposed =Window ]interface :
XRBoundedReferenceSpace XRReferenceSpace {readonly attribute FrozenArray <DOMPointReadOnly >boundsGeometry ; };
XRBoundedReferenceSpace
の原点は必ず床上(Y
軸が床レベルで0
)に配置されなければなりません。X
・Z
の位置や向きは基盤プラットフォームの慣例に基づき初期化され、通常は部屋の中央付近で論理的前方を向くことが期待されます。
注記: 他のXRプラットフォームでは、bounded-floor
リファレンススペースによるトラッキングを「ルームスケール」トラッキングなどと呼ぶことがあります。XRBoundedReferenceSpace
は複数部屋、床高さが不均一な場所、非常に広い空間を扱うことは想定していません。これらに対応するにはunbounded
リファレンススペースを使うべきです。
各XRBoundedReferenceSpace
は、ユーザーが安全に移動できる範囲の境界を記述するネイティブ境界ジオメトリを持ちます。多角形境界はDOMPointReadOnly
配列として与えられ、安全空間の縁にある点のループを表現します。各点は原点からのメートル単位のオフセットです。点は上から見て時計回り(Y軸負方向から見下ろし)で並べる必要があります。各点のy
値は0
、w
値は1
でなければなりません。境界は床上から無限に上方へ広がると考えます。形状は凸でも凹でも可です。
ネイティブ境界ジオメトリ内の各点は、そのリファレンススペースのネイティブ原点から合理的な距離内に制限されなければなりません。
注記: ネイティブ境界ジオメトリの点は、すべての方向で原点から15メートル以内に制限することが推奨されます。
ネイティブ境界ジオメトリ内の各点は、フィンガープリント防止のため十分に量子化されなければならず、ユーザー安全のため量子化後の点がプラットフォーム報告境界外になってはなりません。
注記: ネイティブ境界ジオメトリの点は5cm単位で量子化することが推奨されます。
boundsGeometry
属性は、
DOMPointReadOnly
の配列です。
各エントリは、XRBoundedReferenceSpace
の
ネイティブ境界ジオメトリの各エントリに、
inverse
を掛けたものと等しくなります。つまり、これは有効原点に対して
XRBoundedReferenceSpace
座標で同じ境界線を提供します。
ネイティブ境界ジオメトリが一時的に利用不可な場合(XRデバイス初期化・追跡ロス長期化・事前構成空間間の移動など)、boundsGeometry
は空配列を返さなければなりません。
注記: 境界や床高さがリファレンススペース要求時点で未確定でも、デバイスがサポートしていれば境界付きリファレンススペースが返される場合があります。
注記: コンテンツはboundsGeometry
外へのユーザーの移動を必須にすべきではありません。物理的に可能なら境界外にも移動でき、その場合ポリゴン外の値になりますが、これはエラーではなくページ側で丁寧に処理すべきです。
注記: 安全に関わる情報はユーザーエージェントが管理すべきなので、boundsGeometry
の可視化は一般にコンテンツ側で行うべきではありません。
7. ビュー
7.1. XRViewGeometry
XRViewGeometry
インターフェイスミックスインを含むオブジェクトは、ユーザーへの画像提示用ディスプレイや、現実世界の映像情報収集用センサーなどであり、ビュー幾何を持ちます。
ビュー幾何は、ビューアリファレンススペースの座標系と、含有オブジェクトのスクリーンスペース間の変換に使う内在パラメータ・外在パラメータセットです。
ビュー幾何には含有オブジェクト(このビュー幾何がデータを持つ物理ハードウェア)が関連付けられます。
ビュージオメトリの包含オブジェクトには、関連付けられたスクリーンスペースが存在します。これは、この包含オブジェクトがデータを読み取るか、またはデータを描画する2D平面として記述されます。
ビュー幾何にはビューオフセット(XRRigidTransform
、含有オブジェクトのビューアリファレンススペースでの位置・向き)が関連付けられます。
注記: ビューオフセットに制約はなく、ビューごとに向きも異なり得ます。HMDで目のディスプレイが角度付きで配置されていたり、CAVEレンダリングのような極端なケースでも起こり得ます。このためzソートやカリング等を目ごとに行う必要がある場合があります。
ビュー幾何には投影行列(基盤XRデバイスが与える含有オブジェクト描画時の行列)も関係付けられます。この投影行列は、単純なフラスタムで表せないシアー変換などを含む場合もあります。
注記: この行列の逆行列は、スクリーンスペース上のピクセルを座標系(含有オブジェクトが原点)へ戻すのに使えます。
[SecureContext ,Exposed =Window ]interface mixin {
XRViewGeometry readonly attribute Float32Array projectionMatrix ; [SameObject ]readonly attribute XRRigidTransform transform ; };
各XRViewGeometry
には、その含有オブジェクトの投影行列を格納する、初期値null
の内部投影行列が関連付けられています。
注記: transform
は多くのレンダリングライブラリでカメラオブジェクトの配置に利用できます。従来のビュー行列が必要なら transform.inverse.matrix
で得られます。
projectionMatrix
属性は、基盤ビュー幾何の投影行列です。アプリケーションはこの行列を改変・分解せずそのまま使うことが強く推奨されます。これを用いずに描画すると、フレームが歪んだり不整合を起こし、ユーザーに不快感を与えることがあります。この属性は投影行列の取得で計算されなければなりません。
transform
属性はこのオブジェクトのXRRigidTransform
であり、取得元XRReferenceSpace
での位置・向きを表します。
XRViewGeometry
view geometryについて投影行列の取得を行うには:
-
もしview geometryのinternal projection matrixが
null
でない場合、以下の手順を実行する:-
internal projection matrixに対して操作
IsDetachedBuffer
を行い、その結果がfalse
であれば、view geometryのinternal projection matrixを返す。
-
-
view geometryのinternal projection matrixに、 新しい matrix(view geometryの 関連realmで、view geometryのprojection matrixと等しいもの)を設定する。
-
view geometryのinternal projection matrixを返す。
7.2. XRView
XRView
は、あるフレームのXRシーンにおける1つのビューを記述します。
ビューは、XRデバイスがユーザーに画像を提示するために用いるディスプレイまたはその一部に対応します。ビューは、視野・アイオフセット・その他の光学特性など、ビューの物理的出力特性に正確に合わせて描画するために必要な情報を取得するために使われます。ビューはユーザーの視野の重複領域もカバーし得ます。どのXRデバイスが何個のビューを使うかや順序について保証はなく、XRSession
の期間中もビュー数は一定である必要はありません。
ビューには、どちらの目に表示するかを示すeye(XREye
)が関連付けられます。ビュー自体が目に紐付かない場合(単眼ディスプレイ等)は、この値は"none"
でなければなりません。
ビューには、XRSession
のライフサイクル中に変化しうるactiveフラグがあります。プライマリビューは常にactiveフラグがtrue
でなければなりません。
注記: 多くのHMDは左目・右目用の2つのビューを要求しますが、マジックウィンドウデバイスは1つのみの場合が多いです。ただしアプリケーションはビュー構成を仮定すべきではありません。例えばマジックウィンドウデバイスでもステレオ出力対応時は2ビューを要求し、パフォーマンス理由で1ビューに戻ることもあります。同様に、HMDも広視野や異なるピクセル密度表示のため2つ以上のビューを要求する場合があります。
ビューには、viewport
modifiableフラグ(この時点でrequestViewportScale()
でビューポートスケール変更可能か)があり、アニメーションフレーム開始時にtrue
、getViewport()
呼び出しでfalse
になります。
ビューには、システムが動的ビューポートスケーリングをサポートする場合にrequestViewportScale()
で変更できるリクエスト済みスケール値requested viewport scaleがあります。初期値は1.0。
ビューには、システム内部で現在使用中のスケール値current viewport
scaleがあります。初期値は1.0。getViewport()
でリクエスト済みスケールに更新されます。
ビューには、reference
space(このビューをgetViewerPose()
で取得した際のXRReferenceSpace
)があります。
注記:
動的ビューポートスケーリングでは、フレーム単位でスケールを効率的に切り替えられます。描画の正確性のためアプリケーションとXRシステムがアクティブなビューポートで合意している必要があります。アプリケーションは1フレーム中に複数回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
属性は、基礎となるeyeを示します。これはプリレンダーステレオコンテンツで左右の内容を正しい目に表示するために重要です。
index
属性は、この XRView
が
views
配列内で getViewerPose()
により返される際のオフセットを示します。
オプションのrecommendedViewportScale
属性は、UAが推奨するビューポートスケール値です。アプリケーションはこれをrequestViewportScale()
に使えます。システムが推奨値決定メソッドを持たない場合はnull
。nullでない場合は0.0より大きく1.0以下の数値かつ量子化済みでなければなりません。
注記: 推奨ビューポートスケールは、短い候補値リストへの丸めやヒステリシスを使って量子化し、境界付近で即座に変化しないようにするのが推奨されます(急激なスケール振動は不快感を与えるため)。
各XRView
には、それを生成したsession(XRSession
)があります。
各XRView
には、それを生成したframe(XRFrame
)があります。
各XRView
には、表現する基礎となるunderlying view(view)があります。
requestViewportScale(scale)
メソッドは、このビューポートのrequested viewport scaleを指定値に設定するようユーザーエージェントに要求します。
このメソッドがXRView
xrviewで呼び出された場合、ユーザーエージェントは次の手順を実行します:
-
scaleがnullまたはundefinedなら中止。
-
scaleが0.0以下なら中止。
-
scaleが1.0より大きい場合、scaleを1.0にする。
-
viewをxrviewのunderlying viewとする。
-
viewのrequested viewport scale値をscaleに設定する。
注記:
nullやundefinedのスケール値を無視することで、推奨スケール未対応システムでもview.requestViewportScale(view.recommendedViewportScale)
を安全に呼べます。
いずれかのactiveフラグがビューリスト内で変化した場合、XRSession
sessionについて次の手順でビューポートを更新できます:
-
layerを
renderState
のbaseLayer
とする。 -
layerが
null
なら中止。 -
layerのビューポートオブジェクトリストを空リストに設定。
-
-
viewportをfull-sized viewportリストからスケール済みビューポートの取得で得る。
-
Appendでviewportをlayerのビューポートオブジェクトリストに追加。
-
XRView
view、XRSession
sessionについてスケール済みビューポートの取得を行うには:
-
glFullSizedViewportをviewに紐付くWebGL viewport(full-sized viewportリスト)とする。
-
scaleをviewのcurrent viewport scaleとする。
-
ユーザーエージェントはscaleに最小スケールファクタを適用してもよい。
-
glViewportを新しいWebGL viewportとする。
-
glViewportの
width
を、glFullSizedViewportのwidth
×scale以下の整数値に設定。 -
glViewportの
width
が1未満なら1に設定。 -
glViewportの
height
を、glFullSizedViewportのheight
×scale以下の整数値に設定。 -
glViewportの
height
が1未満なら1に設定。 -
glViewportの
x
を、glFullSizedViewportのx
以上、かつglFullSizedViewportのx
+glFullSizedViewportのwidth
-glViewportのwidth
以下の整数値に設定。 -
glViewportの
y
を、glFullSizedViewportのy
以上、かつglFullSizedViewportのy
+glFullSizedViewportのheight
-glViewportのheight
以下の整数値に設定。 -
viewportをsessionの新しい
XRViewport
とする(関連realm)。 -
viewportの
x
をglViewportのx
に設定。 -
viewportの
y
をglViewportのy
に設定。 -
viewportの
width
をglViewportのwidth
に設定。 -
viewportの
height
をglViewportのheight
に設定。 -
viewportを返す。
注記: 幅/高さの計算はUAに委ねられています。単純な切り捨ても有効ですが、パワーオブツー境界に合わせる等、範囲内で調整しても構いません。スケール済みビューポートはfull-sized viewport内に完全に収まる必要がありますが、配置はUA裁量です。計算はセッション内で同じ入力に対し必ず同じ結果を返さなければなりません。
7.3. プライマリビューとセカンダリビュー
ビューは、没入型体験において描画が必須な場合、プライマリビューとなります。プライマリビューは、XRSession
の期間中常にactiveでなければなりません。
ビューは、コンテンツがそれに描画しなくても没入型体験が成立する場合、セカンダリビューとなります。これらのビューにコンテンツが描画しない場合、ユーザーエージェントはリプロジェクション等で再構成できる場合があります。セカンダリビューは、"secondary-views"機能が有効でない限り、activeであってはなりません。
セカンダリビューの例としては、ビデオキャプチャ用の一人称オブザーバービューや、1つの目に2つの異なる解像度・視野のビューがある「クワッドビュー」などがあります。
views
配列の内容を誤って仮定し、2つを超えるビューで動作しなくなると予想されます。
ユーザーエージェントはリプロジェクションなどの仕組みでセカンダリビューへの描画を代替できる場合があるため、コンテンツがこれらのセカンダリビューを自力で扱うつもりか、そうでないかを区別できることが望ましいです。
このため、セカンダリビューを公開するユーザーエージェントは、ヒントとして"secondary-views"フィーチャーディスクリプタをサポートしなければなりません。この機能を有効化したコンテンツは次を想定してください:
-
views
配列のサイズがフレームごとに変化することに対応する。(例:ビデオキャプチャ有効時など)
"secondary-views"が有効な場合、ユーザーエージェントは必要に応じて、デバイスがサポートするセカンダリビューをXRSession
に公開してもかまいません。この場合、ユーザーエージェントはリプロジェクションによるセカンダリビュー再構成を行わず、コンテンツ側の描画に従う必要があります。
注記: 最大限の互換性のため、optionalFeatures
で"secondary-views"を有効化することを推奨します。
セカンダリビューが低いフレームレートで動作する場合、XRSession
は次の対応を取ることがあります:
-
セカンダリビューがactiveの間、アプリ全体のフレームレートを下げる。
-
一部のフレームだけ
views
配列にセカンダリビューを含める(この場合もプライマリビュー
が欠落するフレームは作らないこと)。 -
一部のフレームでセカンダリビューの描画内容を黙って破棄する。
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の慣例に依存します:
-
XRWebGLLayer
で使う場合、x
およびy
はピクセル単位でビューポート矩形の左下隅を示し、そこから右にwidth
ピクセル、上にheight
ピクセル広がる矩形を表します。値はWebGL viewport関数にそのまま渡せます。
XRView
すべてについて、XRViewerPose
から取得し、各XRWebGLLayer
でXRViewport
を取得して、適切なWebGL viewportで描画する例です。
xrSession. requestAnimationFrame(( time, xrFrame) => { const viewer= xrFrame. getViewerPose( xrReferenceSpace); gl. bindFramebuffer( xrWebGLLayer. framebuffer); for ( xrViewof 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は各種変換を行列の形式で提供します。WebXRではWebGLの慣例に従い、4x4行列は16要素のFloat32Array
(カラムメジャー)として渡され、列ベクトルに対して左側から前置乗算で適用されます。そのままWebGLのuniformMatrix4fv
関数に渡したり、DOMMatrix
相当の生成や、外部の数値ライブラリでも利用可能です。
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
にする)するアルゴリズムがいくつかあります。
normalizeを成分リストに対し行うには、UAは次の手順を実行しなければなりません:
-
各成分の2乗和の平方根をlengthとする。
-
lengthが
0
ならInvalidStateError
をスローし中止。 -
各成分をlengthで割り、成分値を設定する。
8.3. XRRigidTransform
XRRigidTransform
は、position
とorientation
で記述される変換です。
XRRigidTransform
を解釈する際は、orientation
が常にposition
より先に適用されます。
XRRigidTransform
には行列である内部行列を持ちます。
[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)
コンストラクタが呼び出されたとき、次の手順を実行しなければなりません:
-
transformを新しい
XRRigidTransform
(current realm)とする。 -
transformの
position
を新しいDOMPointReadOnly
(current realm)とする。 -
positionやorientationのいずれかの値が
NaN
や非有限値(無限大等)なら、TypeError
をスローし中止。 -
transformの
position
のx
をpositionのx辞書メンバー、y
をyメンバー、z
をzメンバー、w
をwメンバーに設定。 -
transformの
orientation
を新しいDOMPointReadOnly
(current realm)とする。 -
transformの
orientation
のx
をorientationのxメンバー、y
をyメンバー、z
をzメンバー、w
をwメンバーに設定。 -
transformの内部行列を
null
に設定。 -
transformを返す。
position
属性は、変換の並進成分を示す3次元点(単位:メートル)です。position
の
w
属性は1.0
でなければなりません。
orientation
属性は変換の回転成分を示すクォータニオンです。orientation
はノルムが1.0
に正規化されていなければなりません。
matrix
属性は、position
と
orientation
で記述される変換を行列として返します。この属性はXRRigidTransform
に対し行列の取得で計算されなければなりません。
注記: この行列を列ベクトルに前置乗算すると、まずorientation
で回転し、その後position
で平行移動します。数式的には列ベクトル表記でM = T * R
(T=平行移動,
R=回転)です。
XRRigidTransform
transformについて行列の取得を行うには:
-
もしtransformのinternal matrixが
null
でない場合、以下の手順を実行する:-
internal matrixに対し
IsDetachedBuffer
操作を行い、その結果がfalse
であれば、transformのinternal matrixを返す。
-
-
translationを新たなmatrixとし、これは
position
に対応するカラムベクトル形式の並進行列である。 数学的には、position
が(x, y, z)
のとき、この行列は次の通り。 -
rotationを新たなmatrixとし、これは
orientation
に対応するカラムベクトル形式の回転行列である。 数学的には、orientation
が単位クォータニオン (qx, qy, qz, qw
)のとき、この行列は次の通り。 -
transformのinternal matrixを、新しい
Float32Array
(transformの関連realmで、translationとrotationをtranslationを左にして乗算した結果(translation * rotation
)で初期化)に設定する。 数学的には、この行列は以下の通り。 -
transformのinternal matrixを返す。
inverse
属性は、XRRigidTransform
transformで、同じrealm内でtransformで変換済みのオブジェクトに適用すると元の姿勢に戻すことができるXRRigidTransform
を返します。この属性は遅延評価されるべきです。inverse
で返されたインスタンスはtransformをinverse
として返さなければなりません。
XRRigidTransform
でposition
が{ x: 0, y: 0, z: 0 w: 1 }
、orientation
が{ x: 0, y: 0, z: 0, w: 1 }
のものを単位変換と呼びます。
2つのXRRigidTransform
の乗算
(B・A、Realmrealm)は、UAが次の手順を実行します:
-
resultをrealmで新しい
XRRigidTransform
とする。 -
resultの
matrix
を、realmで新しいFloat32Array
、Aのmatrix
にBのmatrix
を左から前置乗算した結果に設定。 -
resultの
orientation
を、realmで新しいDOMPointReadOnly
、resultのmatrix
左上3×3部分行列が表すクォータニオンに設定。 -
resultの
position
を、realmで新しいDOMPointReadOnly
、resultのmatrix
第4列ベクトルに設定。 -
resultを返す。
resultはAのソース空間からBのデスティネーション空間への変換です。
注記: これは、XRRigidTransform
を構築するのと同等です。そのorientation
はAのorientationとBのorientationの合成、position
はAのposition
をBのorientation
で回転させ、
Bのposition
を加えたものと等しいです。
9. Pose
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
値に首や腕モデルのような計算オフセットが含まれる場合はtrue
となります。推定床レベルは、XRPose
が計算オフセットを含むかどうかの判定には利用してはいけません。
9.2. XRViewerPose
XRViewerPose
は、XRデバイスによってトラッキングされるXRシーンのビューアの状態を表すXRPose
です。ビューアは、トラッキングされたハードウェア、ハードウェアに対するユーザー頭部の観測位置、またはXRシーンへの一連の視点を計算する他の手段などを表す場合があります。XRViewerPose
はXRReferenceSpace
に対してのみクエリ可能です。これは、XRPose
の値に加え、視点や投影行列を示す剛体変換を含むビューの配列を提供します。これらの値はXRシーンのフレームを描画する際にアプリケーションが利用すべきものです。
[SecureContext ,Exposed =Window ]interface :
XRViewerPose XRPose { [SameObject ]readonly attribute FrozenArray <XRView >views ; };
views
配列は、XRViewerPose
がクエリされたXRReferenceSpace
基準でXRシーンの視点を記述するXRView
の列です。この配列のすべてのビューを描画しなければXRデバイス上で正しく表示できません。各XRView
は視点・投影行列を示す剛体変換を含み、必要に応じてレイヤーからXRViewport
を問い合わせることができます。
注記: XRViewerPose
のtransform
は、シーンの観戦者ビューやマルチユーザーインタラクション向けのビューアのグラフィックス表現の配置に利用できます。
10. 入力
10.1. XRInputSource
XRInputSource
は、XR入力ソースを表します。これは、ユーザーがviewerと同じ仮想空間内でターゲットアクションを実行できるあらゆる入力手段です。XR入力ソースの例としては、ハンドヘルドコントローラー、光学的にトラッキングされた手、viewerの姿勢に基づく視線入力方式などがあります。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 Module によっても拡張されます。
handedness
属性は、このXR入力ソースがどちらの手に対応するかを示します。自然な利き手を持たない入力ソース(ヘッドセット取り付け型コントローラ等)や現在利き手が不明な場合は、この属性を"none"
に設定しなければなりません。
targetRayMode
属性はターゲットレイの生成方法を示し、アプリケーションがユーザーにターゲットレイをどのように表示すべきかを示します。
-
gaze
はターゲットレイがviewerから発し、向いている方向に従うことを示します(HMD文脈では「視線入力」デバイスと呼ばれます)。 -
tracked-pointer
は、ターゲットレイがハンドヘルドデバイスや他の手トラッキング機構から発し、ユーザーが手やデバイスで指し示していることを表します。レイの向きは可能な限りプラットフォームの人間工学ガイドラインに従う必要があります。ガイドラインがない場合、ユーザーが人差し指を伸ばした方向にレイが向くべきです。XRSystem
がデバイスの一部(例:ペン先)が実世界の表面に接触する意図があると判断した場合、レイの起点はその点でなければなりません。 -
screen
は、入力ソースがインラインセッションのcanvas要素へのマウスクリックやタッチイベントなどの操作であることを示します。 -
transient-pointer
は、入力ソースが特定のハードウェアでなくOSのインタラクション意図から生成されたことを示します。例として、直接公開できない視線情報に基づくもの、WebDriverによる合成入力や支援技術による入力などがあります。この値は支援技術が主入力としても使われる場合にのみ用いるべきです(W3C設計原則に従い、支援技術利用を意図せず示唆しないため)。
targetRaySpace
属性はXRSpace
であり、targetRayMode
で定義されるXRInputSource
の推奨指向レイ(-Z軸方向)の位置・姿勢をトラッキングします。
targetRayMode
が"transient-pointer"
の場合、このtargetRaySpace
はインタラクション開始時のターゲットへのレイを表します。この姿勢は当該XRInputのgripSpace内で静的であるべきです。
gripSpace
属性はXRSpace
であり、バーチャルオブジェクトがユーザーの手に握られて見えるようにするための姿勢をトラッキングします。ユーザーが棒を持った場合、このXRSpace
の原点は指を握った中心に置かれ、-Z軸が親指方向に棒の長さ方向を指します。X軸は手の甲に垂直で、右手の甲は+X、左手の甲は-X方向、Y軸はX軸とZ軸の関係から決まり、+Y軸はおおよそ腕方向になります。
skipRendering
属性は、この入力が可視であり、現在のセッションでレンダリング不要かもしれないことを示します。skipRendering
がtrueかつtargetRayModeが"tracked-pointer"なら、ユーザーエージェントは必ずXR入力ソースの表示をユーザーに保証しなければなりません。
コントローラーがユーザーに見える例としては、コントローラーがディスプレイとユーザーの間にある、ディスプレイが透明である、またはコントローラーがOSによって描画される場合などがあります。
skipRendering
は、コントローラーなどの入力ソースの描画省略に関する開発者向けヒントです。レイやカーソルは描画すべきです。
targetRayMode
が"transient-pointer"
の場合、gripSpace
は関連ユーザーのジェスチャ空間があればそれを、なければViewerSpaceや他のXRInputのgripSpace/targetRaySpace等を使うべきです。これはユーザーがtargetRaySpaceを操作できるようにするためです。
gripSpace
は、入力ソースが本質的にトラッキング不可な場合(targetRayModeが"gaze"
や"screen"
の場合)はnull
でなければなりません。
profiles
属性は、入力ソースの推奨ビジュアル表現や挙動を示すリスト(入力プロファイル名)です。
入力プロファイル名は、スペースなしASCII小文字DOMString
で、単語は-
で連結します。説明的な名称は可能ならデバイスベンダの用語を使うべきです。プラットフォームが適切なID(USBベンダID等)を与える場合は利用可。シリアル番号など一意個体識別値は禁止。入力プロファイル名には利き手情報を含めてはいけません。同一デバイスを複数UAが公開する場合は同じ入力プロファイル名を報告する努力をすること。管理にはWebXR Input
Profiles Registryの利用が推奨されます。
プロファイルは特異性の高い順に並びます。リスト2番目以降はfallback値で、より一般的・旧バージョンや類似デバイス・型名(例: "generic-trigger-touchpad")など。複数プロファイルがあれば全て互いにレイアウトが包含/被包含の関係であるべきです。
XRSession
のmodeが"inline"
なら、profiles
は空リストでなければなりません。
UAは適宜、汎用入力プロファイル名や空リストのみを返しても構いません。これはデバイスが特定できない・既知プロファイルがない・デバイスを秘匿したい場合などに適用されます。
例:Samsung HMD Odysseyのコントローラーは標準Windows Mixed
Realityコントローラーの設計バリアントで、レイアウトが共通です。この場合、profiles
は
["samsung-odyssey", "microsoft-mixed-reality", "generic-trigger-squeeze-touchpad-thumbstick"]
などとなり、1番目が最も正確な外観を、2番目が許容代替を、最後が大雑把な汎用表現を示します(トリガ・グリップ・タッチパッド・スティック付きコントローラー)。
同様にValve IndexコントローラーはHTC
Viveコントローラーと互換性がありますが機能追加があります。この場合、profiles
は
["valve-index", "htc-vive", "generic-trigger-squeeze-touchpad-thumbstick"]
など。"valve-index"
は"htc-vive"
の上位互換レイアウト、外観は異なるがUAが許容した場合。最後は汎用fallback。
(実際のプロファイル名はWebXR Input
Profiles Registryで管理されます)
注記: XRInputSource
は、XRSession
のinputSources
配列内で「ライブ」です。値はその場で更新されるため、あるフレームでの属性値を保存し次のフレームの属性と比較しても同じオブジェクトとなり状態変化検出には使えません。比較したい場合は値内容をコピーして比較してください。
XR入力ソースは、プライマリ入力ソースである場合、プライマリアクションをサポートします。プライマリアクションは、プラットフォーム固有のアクションで、実行時にselectstart
、selectend
、select
イベントが発生します。例:トリガ・タッチパッド・ボタン押下、音声コマンド、ハンドジェスチャ等。ガイドラインで推奨プライマリ入力が定義されていればそれを使い、なければUAが自由に選択可。デバイスは最低1つのプライマリ入力ソースをサポートしなければなりません。
XR入力ソースは、プライマリアクションをサポートしない場合、トラッキング入力ソースです。これらは主に姿勢データ提供が目的です。 注記: トラッキング入力ソースの例は脚やプロップ用のトラッキングアタッチメント等。ハンドジェスチャ検出しない手トラッキングもこれに該当します。
XR入力ソースsourceが、XRSession
sessionでプライマリアクションを開始したとき、UAは次の手順を実行しなければなりません:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、timeにアクション発生時刻を設定。 -
タスクをキューして、input source event(名前
selectstart
、frame frame、source source)を発火。
XR入力ソースsourceが、XRSession
sessionでプライマリアクションを終了したとき、UAは次の手順を実行しなければなりません:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、timeにアクション発生時刻を設定。 -
タスクをキューして、次を実行:
-
input source event(名前
select
、frame frame、source source)を発火。 -
input source event(名前
selectend
、frame frame、source source)を発火。
-
各XR入力ソースは、プライマリスクイーズアクションを定義しても構いません。プライマリスクイーズアクションは、実行時にsqueezestart
、squeezeend
、squeeze
イベントが発生するプラットフォーム固有アクションです。つかむ・握る操作に相当するアクションで利用してください。例:グリップトリガや握る手ジェスチャ等。ガイドラインで推奨があればそれを使い、なければUAが選択可。
XR入力ソースsourceが、XRSession
sessionでプライマリスクイーズアクションを開始したとき、UAは次の手順を実行しなければなりません:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、timeにアクション発生時刻を設定。 -
タスクをキューして、input source event(名前
squeezestart
、frame frame、source source)を発火。
XR入力ソースsourceが、XRSession
sessionでプライマリスクイーズアクションを終了したとき、UAは次の手順を実行しなければなりません:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、timeにアクション発生時刻を設定。 -
タスクをキューして、次を実行:
-
input source event(名前
squeeze
、frame frame、source source)を発火。 -
input source event(名前
squeezeend
、frame frame、source source)を発火。
-
プラットフォーム固有の動作により、プライマリアクションやプライマリスクイーズアクションが中断・キャンセルされる場合があります。例えば、XR入力ソースがアクション開始後〜終了前にXRデバイスから削除された場合など。
XR入力ソースsourceが、XRSession
sessionでプライマリアクションがキャンセルされたとき、UAは次の手順を実行:
XR入力ソースsourceが、XRSession
sessionでプライマリスクイーズアクションがキャンセルされたとき、UAは次の手順を実行:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、timeにアクション発生時刻を設定。 -
タスクをキューして、input source event(名前
squeezeend
、frame frame、source source)を発火。
10.2. 一時的入力
一部のXRデバイスは、一時的入力ソースをサポートする場合があります。これは、XR入力ソースが一時的アクション(プライマリ入力ソースのプライマリアクション、またはトラッキング入力ソースのデバイス固有補助アクション)の実行中のみ意味を持つものです。
例えば、"inline"
XRSession
でのマウス・タッチ・スタイラス入力は、XRInputSource
(targetRayMode
がscreen
)として一時的に生成され、プライマリポインタに対してはプライマリアクションとして、非プライマリポインタでは補助アクションとして扱われます。
もう一つの例は、視線などセンシティブな情報から直接公開できないOSインテントによる入力です。これらは、XRInputSource
(targetRayMode
がtransient-pointer
)として一時的に生成され、プライマリアクションとして扱われます。
一時的入力ソースは、一時的アクションの継続中のみセッションのアクティブなXR入力ソースのリストに存在します。
一時的入力ソースは、プライマリアクションの非一時的なアルゴリズムの代わりに、次の手順で一時的アクションを処理します:
一時的入力ソースsourceがXRSession
sessionで一時的アクションを開始したとき、UAは次の手順を実行:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、アクション発生時刻を設定。 -
タスクをキューして、次を実行:
-
必要に応じてXR入力ソースのアクションによって生成された
"pointerdown"
イベントを発火。 -
一時的アクションがプライマリアクションなら、input source event(名前
selectstart
、frame frame、source source)を発火。
-
一時的入力ソースsourceがXRSession
sessionで一時的アクションを終了したとき、UAは次の手順を実行:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、アクション発生時刻を設定。 -
タスクをキューして、次を実行:
-
一時的アクションがプライマリアクションなら、input source event(名前
select
、frame frame、source source)を発火。 -
必要に応じてXR入力ソースのアクションによる
"click"
イベントを発火。 -
一時的アクションがプライマリアクションなら、input source event(名前
selectend
、frame frame、source source)を発火。 -
必要に応じてXR入力ソースのアクションによる
"pointerup"
イベントを発火。
-
一時的入力ソースsourceがXRSession
sessionで一時的アクションがキャンセルされたとき、UAは次の手順を実行:
-
frameをsessionの新しい
XRFrame
(関連realm)とし、session
をsession、アクション発生時刻を設定。 -
タスクをキューして、次を実行:
-
一時的アクションがプライマリアクションなら、input source event(名前
selectend
、frame frame、source source)を発火。 -
必要に応じてXR入力ソースのアクションによる
"pointerup"
イベントを発火。
-
10.3. XRInputSourceArray
XRInputSourceArray
は、リスト
(XRInputSource
のリスト)
を表します。frozen array typeの代わりに、
リストの内容が時間とともに変化することが想定される場合(例えばXRSession
のinputSources
属性など)に使用されます。
[SecureContext ,Exposed =Window ]interface {
XRInputSourceArray iterable <XRInputSource >;readonly attribute unsigned long length ;getter XRInputSource (unsigned long ); };
index
XRInputSourceArray
のlength
属性は、
XRInputSourceArray
内に含まれる
XRInputSource
の数を示します。
XRInputSourceArray
のインデックスプロパティゲッターは、指定したインデックスの
XRInputSource
を取得します。
11. レイヤー
注記: 本仕様ではXRWebGLLayer
レイヤーのみ定義されていますが、将来的な拡張で他のレイヤー種や画像ソースも追加される予定です。
11.1. XRLayer
[SecureContext ,Exposed =Window ]interface :
XRLayer EventTarget {};
XRLayer
は、
XRWebGLLayer
や将来の拡張で導入される他のレイヤー型の基底クラスです。
11.2. XRWebGLLayer
XRWebGLLayer
は、WebGLフレームバッファを描画先として提供し、XRデバイス上で3Dグラフィックスのハードウェアアクセラレート描画を実現するレイヤーです。
typedef (WebGLRenderingContext or WebGL2RenderingContext );
XRWebGLRenderingContext dictionary {
XRWebGLLayerInit boolean =
antialias true ;boolean =
depth true ;boolean =
stencil false ;boolean =
alpha true ;boolean =
ignoreDepthValues false ;double = 1.0; }; [
framebufferScaleFactor SecureContext ,Exposed =Window ]interface :
XRWebGLLayer XRLayer {constructor (XRSession ,
session XRWebGLRenderingContext ,
context optional XRWebGLLayerInit = {}); // Attributes
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 ; // MethodsXRViewport ?getViewport (XRView ); // Static Methods
view static double getNativeFramebufferScaleFactor (XRSession ); };
session
各XRWebGLLayer
は、初期値null
のcontextオブジェクトを持ちます。これはWebGLRenderingContext
またはWebGL2RenderingContext
のインスタンスです。
各XRWebGLLayer
は、生成時に使われたXRSession
を関連付けられたsessionとして持ちます。
XRWebGLLayer(session, context, layerInit)
コンストラクタが呼び出されたとき、次の手順を実行しなければなりません:
-
layerをsessionの関連realmでXRWebGLLayerの新しいインスタンスとする。
-
sessionのended値が
true
なら、InvalidStateError
をスローし中止。 -
contextがロストしていれば、
InvalidStateError
をスローし中止。 -
sessionが没入型セッションで、contextのXR compatibleブール値が
false
なら、InvalidStateError
をスローし中止。 -
layerのcontextをcontextに初期化。
-
layerのsessionをsessionに初期化。
-
layerの
ignoreDepthValues
を次のように初期化:- layerInitの
ignoreDepthValues
値がfalse
かつXRコンポジタがdepth値を利用する場合: -
layerの
ignoreDepthValues
をfalse
に初期化。 - それ以外の場合:
-
layerの
ignoreDepthValues
をtrue
に初期化。
- layerInitの
-
layerのcomposition enabledブール値を次のように初期化:
- sessionがインラインセッションの場合:
-
layerのcomposition enabledを
false
に初期化。 - それ以外の場合:
-
layerのcomposition enabledを
true
に初期化。
-
- layerのcomposition
enabledが
true
の場合: -
-
scaleFactorをlayerInitの
framebufferScaleFactor
とする。 -
UAはここでscaleFactorをパフォーマンス上パワーオブツー等に丸めてもよい。
-
framebufferSizeを推奨WebGLフレームバッファ解像度の幅・高さにscaleFactorを個別乗算したものとする。
-
layerの
framebuffer
をcontextの関連realmで新しいWebGLFramebuffer
(opaqueフレームバッファ、サイズframebufferSize、contextで生成、sessionをsessionで初期化、layerInitのdepth
・stencil
・alpha
値で)に初期化。 -
layerの合成をサポートするため、必要に応じてsessionのXRデバイス互換のリソース(GPUバッファ等)を割り当て・初期化。
-
リソース初期化に失敗した場合は
OperationError
をスローし中止。
- それ以外の場合:
-
-
layerの
antialias
をlayerのcontext
の実際のコンテキストパラメータのantialias
値に初期化。 -
layerの
framebuffer
をnull
に初期化。
-
- layerのcomposition
enabledが
-
layerを返す。
注記: XRWebGLLayer
の
composition enabled ブール値がfalse
の場合、
XRWebGLLayerInit
オブジェクト上のすべての値は無視されます。なぜならWebGLRenderingContext
のデフォルトフレームバッファはすでにコンテキストの実際のコンテキストパラメータを使って割り当てられており、上書きできないためです。
context
属性は、WebGLRenderingContext
であり、XRWebGLLayer
が生成された際に使われたものです。
各XRWebGLLayer
は、初期値がtrue
のcomposition
enabledブール値を持ちます。これがfalse
に設定された場合、そのXRWebGLLayer
は独自のWebGLFramebuffer
を割り当ててはならず、XRWebGLLayer
のframebuffer
プロパティに関連するすべてのプロパティは、かわりにcontextのデフォルトフレームバッファのプロパティを反映しなければなりません。
framebuffer
属性は、XRWebGLLayer
の場合、WebGLFramebuffer
のインスタンスであり、composition enabledがtrue
ならopaqueとしてマークされ、そうでなければnull
です。framebuffer
のサイズはXRWebGLLayer
作成後に開発者が調整することはできません。
opaque
framebufferは、通常のWebGLFramebuffer
と同様に機能しますが、以下の点が異なり、デフォルトフレームバッファに近い挙動となります:
-
opaque framebufferはWebGL 1.0であってもアンチエイリアスをサポートしてよい。
-
opaque framebufferのアタッチメントは参照・変更不可。
framebufferTexture2D
、framebufferRenderbuffer
、deleteFramebuffer
、getFramebufferAttachmentParameter
をopaque framebufferに対して呼ぶとINVALID_OPERATION
エラーとなる。 -
opaque framebufferには関連sessionがあり、これはそれが生成された
XRSession
です。 -
opaque framebufferは、
requestAnimationFrame()
コールバック外では不完全とみなされます。sessionのrequestAnimationFrame()
コールバック外でcheckFramebufferStatus
を呼ぶとFRAMEBUFFER_UNSUPPORTED
エラー、クリア・描画・読み出しもINVALID_FRAMEBUFFER_OPERATION
エラーとなる。 -
opaque framebufferが
depth
true
で初期化されていれば、デプスバッファがアタッチされる。 -
opaque framebufferが
stencil
true
で初期化されていれば、ステンシルバッファがアタッチされる。 -
opaque framebufferのカラーバッファには、
alpha
がtrue
の場合のみアルファチャネルが含まれる。 -
XR Compositorは、 opaque framebufferがプリマルチプライドアルファの色を含むものとみなします。これは、
premultipliedAlpha
の値がcontext
の actual context parametersでどう設定されていても同様です。
注記: UAはdepth
およびstencil
がtrue
の場合、WebGLのdrawing buffer生成時と同様に、これを尊重する必要があります。
opaque
framebufferにアタッチされているバッファは、初回生成時または各XRアニメーションフレーム処理前に下表の値でクリアされなければなりません。これはWebGLコンテキストのデフォルトフレームバッファと同一挙動です。Opaque framebufferは関連WebGLコンテキストのpreserveDrawingBuffer
値に関係なく必ずクリアされます。
バッファ | クリア値 |
---|---|
Color | (0, 0, 0, 0) |
Depth | 1.0 |
Stencil | 0 |
注記: 実装は必要な場合、opaque framebufferの暗黙クリア操作を最適化して省略できます(開発者が明示的にクリアした場合など)。ただし他プロセスからバッファ内容にアクセスできないことが保証できる場合のみです。
XRWebGLLayer
がalpha
true
で生成された場合、framebuffer
はRGBA
カラーフォーマットのテクスチャで裏打ちされます。
XRWebGLLayer
がalpha
false
で生成された場合、framebuffer
はRGB
カラーフォーマットのテクスチャで裏打ちされなければなりません。
ただしXR Compositor
はframebuffer
の裏打ちピクセルをSRGB8_ALPHA8
またはSRGB8
colorFormat
であるかのように扱う必要があります。
注記: これはXR CompositorがRGBA
やRGB
からリニア→ガンマ変換をしてはならないことを意味します。そうしないと最終描画が明るくなり、通常の2D
WebGLRenderingContext
の描画と一致しません。
XRWebGLLayer
が没入型セッションのbaseLayer
に設定された場合、opaque
framebufferの内容はXRアニメーションフレーム終了直後に没入型XRデバイスに提示されます。ただし前回のXRアニメーションフレーム以降、次のいずれかが発生している場合のみです。
-
clear
、drawArrays
、drawElements
、 または同様にフレームバッファの色値に影響する描画操作が、このXRWebGLLayer
に紐付くWebGLRenderingContext
でopaque framebufferがバインドされている状態で呼ばれた。
opaque framebufferが没入型XRデバイスに提示される直前、UAはすべての描画操作がopaque framebufferにフラッシュされていることを保証します。
各XRWebGLLayer
には、target framebufferがあり、これはframebuffer
(composition enabledがtrue
の時)またはcontextのデフォルトフレームバッファ(それ以外)です。
framebufferWidth
属性とframebufferHeight
属性は、target
framebufferのアタッチメントの幅と高さを返します。
antialias
属性は、target
framebufferがUA選択の手法でアンチエイリアスをサポートする場合true
、しない場合false
。
ignoreDepthValues
属性がtrue
の場合、XR
Compositorはデプスバッファの値を描画時に利用してはならないことを示します。false
の場合、レイヤーに描画したシーンのデプスバッファ内容がXR Compositor
によって利用されることを意味します。
バッファ内のデプス値は0.0
(depthNear
の距離)から1.0
(depthFar
の距離)まで、WebGLのデフォルトのようにリニアに補間されます。(詳細はdepthRange関数参照)
注記: シーンのデプスバッファをコンポジタで利用できると、一部プラットフォームで高品質リプロジェクションなどの品質・快適性向上が可能となります。
fixedFoveation
属性はXR
Compositorによるフォベーション量を制御します。UAやデバイスがこの属性をサポートしない場合、取得時null
、設定はno-opとしてください。fixedFoveation
に0未満を設定すると0に、1超を設定すると1になります。0は最小、1は最大のフォベーションです。解釈はUA依存です。値変更は次のXRFrame
から反映されます。
注記: 固定フォベーションは、ユーザー視野端の描画解像度を下げる手法で、GPUフィルレート制約経験の改善に有効です。消費電力低減・アイテクスチャ解像度向上にも役立ちます。背景画像など低コントラストには有効ですが、テキストや高詳細画像にはあまり適しません。パフォーマンスと画質の最適バランスのため、フレームごとに調整することができます。
各XRWebGLLayer
は、全サイズビューポートのリストを必ず持たなければなりません。これは、リストであり、XRSession
が公開する可能性のある各viewごとにWebGL
ビューポートを1つ含みます。これには、現在アクティブではないが、セッション中にアクティブになる可能性のあるセカンダリビューも含みます。各ビューポートはwidth
および
height
が0
より大きく、かつターゲットフレームバッファの範囲を超えない矩形でなければなりません。ビューポート同士が重なってはなりません。composition enabledがfalse
の場合、全サイズビューポートのリストは、contextのデフォルトフレームバッファ全体を覆う単一のWebGL ビューポートのみを含まなければなりません。
各XRWebGLLayer
は、list of viewport
objects(リスト)を持ち、これは現在XRSession
が公開する各アクティブビューごとに1つのXRViewport
を含みます。
getViewport()
は、指定されたXRView
がこのレイヤーに描画する際に使用すべきXRViewport
を返します。
getViewport(view)
メソッドは、XRWebGLLayer
layerで呼び出された場合、次の手順を実行します:
-
sessionをviewのsessionとする。
-
frameをsessionのanimation frameとする。
-
sessionがlayerのsessionでなければ
InvalidStateError
をスローし中止。 -
frameのactiveブール値が
false
ならInvalidStateError
をスローし中止。 -
viewのframeがframeでなければ
InvalidStateError
をスローし中止。 -
viewport modifiableフラグが
true
かつ viewのrequested viewport scale≠current viewport scaleなら:-
list of viewport objects内で、 viewに紐付く
XRViewport
をobtain a scaled viewportの結果で更新。
-
viewのviewport modifiableフラグをfalseに設定。
-
viewportをviewに紐付くlist of viewport objectsから取得。
-
viewportを返す。
注記: viewport
modifiableフラグは、current viewport
scaleに変更がなくても意図的にfalseに設定されます。これにより、getViewport(view)
の呼び出しはそのアニメーションフレーム内で常に一貫した結果を返し、最初に取得された値がそのフレームの残りの間ロックされます。アプリケーションがrequestViewportScale()
をgetViewport()
の後に呼び出した場合、その値は次のフレームで再度getViewport()
が呼ばれるまで適用されません。
各XRSession
は、ネイティブWebGLフレームバッファ解像度を特定しなければなりません。これは、XRデバイスの物理的なピクセル解像度に一致させるために必要なWebGLフレームバッファのピクセル解像度です。
ネイティブWebGLフレームバッファ解像度は、XRSession
sessionに対して次の手順で決定されます:
-
sessionのmode値が
"inline"
でない場合、 ネイティブWebGLフレームバッファ解像度を、そのセッションの全XRView
を収容できるフレームバッファピクセルと、表示領域の物理スクリーンピクセルが1:1対応するのに必要な解像度とし、これ以降の手順を中止します。記載の方法でネイティブ解像度が決定できない場合は、推奨WebGLフレームバッファ解像度を用いても構いません。 -
sessionのmode値が
"inline"
の場合、 ネイティブWebGLフレームバッファ解像度を、sessionのrenderState
の output canvasの物理ディスプレイピクセルのサイズとし、キャンバスサイズやoutput canvasが変更されるたびに再評価します。
さらに、XRSession
は、推奨WebGLフレームバッファ解像度を特定しなければなりません。これは、セッションの全XRView
を収容可能で、一般的なアプリケーションにとって性能と画質のバランスが良いと見込まれるWebGLフレームバッファ解像度の推定値です。これはネイティブWebGLフレームバッファ解像度より小さくても大きくても同じでも構いません。新しいopaque framebuffer
はこの解像度で作成され、幅と高さはXRWebGLLayerInit
の
framebufferScaleFactor
により個別にスケールされます。
注記: ユーザーエージェントは推奨WebGLフレームバッファ解像度を算出する方法を自由に選択できます。プラットフォーム固有の推奨サイズを取得する方法がある場合はそれを利用することが推奨されますが、必須ではありません。
framebufferScaleFactor
やgetNativeFramebufferScaleFactor()
のスケールは幅・高さ個別に適用されるため、2倍スケールならピクセル数は4倍となります。ピクセル数ベースの面積スケールを公開するプラットフォームでは、その平方根をWebXRスケールファクターに変換する必要があります。
getNativeFramebufferScaleFactor(session)
メソッドが呼び出された時、次の手順を実行します:
-
sessionをthisとする。
-
sessionのended値が
true
なら0.0
を返し、この手順を中止。 -
sessionの推奨WebGLフレームバッファ解像度の幅・高さを個別に乗算してsessionのネイティブWebGLフレームバッファ解像度になる値を返す。
11.3. WebGLコンテキストの互換性
WebGLコンテキストをイマーシブXR画像のソースとして使用するには、互換性のあるグラフィックスアダプター上で作成されている必要があります。何が互換性のあるグラフィックスアダプターとみなされるかはプラットフォーム依存ですが、これはそのグラフィックスアダプターがイマーシブXRデバイスに遅延なく画像を供給できることを意味します。WebGLコンテキストがまだ互換性のあるグラフィックスアダプター上で作成されていない場合、XRWebGLLayer
で利用する前に、通常そのアダプター上で再作成する必要があります。
注記: XRプラットフォームにGPUが1つしかない場合、そのGPUはプラットフォームが広告するイマーシブXRデバイスと互換性があると安全にみなすことができ、ハードウェアアクセラレートされたWebGLコンテキストも同様に互換です。統合型GPUとディスクリートGPUが両方搭載されたPCでは、ディスクリートGPUが一般的に高性能なため、互換性のあるグラフィックスアダプターとみなされることが多いです。複数のグラフィックスアダプターを搭載したデスクトップPCでは、イマーシブXRデバイスが物理的に接続されているアダプターが互換性のあるグラフィックスアダプターとみなされる可能性が高いです。
注記: "inline"
セッションはキャンバスと同じグラフィックスアダプターを使って描画されるため、xrCompatible
コンテキストは不要です。
partial dictionary WebGLContextAttributes {boolean =
xrCompatible false ; };partial interface mixin WebGLRenderingContextBase { [NewObject ]Promise <undefined >makeXRCompatible (); };
ユーザーエージェントが本仕様を実装する際には、すべてのWebGLRenderingContextBase
に、初期値false
のXR
compatibleブール値を設定しなければなりません。XR compatibleブール値がtrue
に設定されると、そのコンテキストは現在のイマーシブXRデバイスからリクエストされた任意のXRSession
用レイヤーで利用できるようになります。
注記: このフラグは遅い同期挙動を引き起こすため推奨されません。非同期的な解決策としてmakeXRCompatible()
を呼び出すことを検討してください。
XR
compatibleブール値は、コンテキスト作成時または作成後に設定でき、その際コンテキストロストが発生する可能性があります。コンテキスト作成時にXR compatibleブール値を設定するには、WebGLコンテキスト取得時にxrCompatible
コンテキスト生成属性をtrue
に指定する必要があります。リクエスト元ドキュメントのオリジンに"xr-spatial-tracking"のPermissions
Policyが許可されていない場合、xrCompatible
は効果を持ちません。
xrCompatible
フラグがWebGLContextAttributes
でtrue
の場合、ユーザーエージェントにWebGLコンテキストを互換性のあるグラフィックスアダプターでイマーシブXRデバイス向けに作成するよう要求します。これに成功した場合、作成されたコンテキストのXR
compatibleブール値はtrueとなります。イマーシブXRデバイスを取得するためには、イマーシブXRデバイスの選択確定を呼び出すべきです。
注記: イマーシブXRデバイスの選択確定は並列で実行する必要があり、メインスレッド上で遅い同期挙動を引き起こします。ユーザーエージェントは、かわりにmakeXRCompatible()
の使用を推奨する警告をコンソールに表示するべきです。
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を利用するかどうかが未定の場合は、イマーシブセッションを開始する際にのみmakeXRCompatible()
を呼び出すことが推奨されます。
makeXRCompatible()
メソッドは、WebGLRenderingContextBase
が互換性のあるグラフィックスアダプター上でイマーシブXRデバイス用に動作していることを保証します。
このメソッドが呼び出されたとき、ユーザーエージェントは次の手順を実行しなければなりません:
-
リクエスト元ドキュメントのオリジンが"xr-spatial-tracking"のPermissions Policyを利用できない場合は、resolve promiseし、それを返す。XR permissions policyが無効な場合、このケースではXRデバイスが存在しないかのように振る舞いたいため、
makeXRCompatible()
はset-and-forgetメソッドとする。 -
promiseを新しいPromiseとして、この
WebGLRenderingContextBase
のRealmで作成する。 -
contextをthisとする。
-
次の手順を並列で実行する:
-
deviceをイマーシブXRデバイスの選択確定の結果とする。
-
contextのXR compatibleブール値を次のように設定する:
- もしcontextのWebGL context lost flagがセットされている場合:
-
タスクをキューに入れて、contextのXR compatibleブール値を
false
にし、InvalidStateErrorでpromiseをrejectする。 - もしdeviceが
null
なら: -
タスクをキューに入れて、contextのXR compatibleブール値を
false
にし、InvalidStateErrorでpromiseをrejectする。 - もしcontextのXR compatibleブール値が
true
なら: -
タスクをキューに入れて、promiseをresolveする。
- もしcontextがdevice用の互換性のあるグラフィックスアダプター上で作成されていた場合:
-
タスクをキューに入れて、contextのXR compatibleブール値を
true
にし、promiseをresolveする。 - それ以外の場合:
-
WebGLタスクソースで次の手順を実行するタスクをキューに入れる:
-
contextを強制的にロストさせる。
-
WebGL仕様に従い、コンテキストロストを処理する:
-
canvasをcontextのキャンバスとする。
-
もしcontextのwebgl context lost flagがセットされていれば、これ以降の手順を中止する。
-
contextのwebgl context lost flagをセットする。
-
contextにより生成された各
WebGLObject
インスタンスのinvalidatedフラグをセットする。 -
"WEBGL_lose_context"以外のすべての拡張機能を無効化する。
-
WebGLタスクソースで次の手順を実行するタスクをキューに入れる:
-
WebGL context event eとして"webglcontextlost"イベントをcanvasに、
statusMessage
を""にして発火する。 -
もしeのcanceled flagがセットされていなければ、AbortErrorでpromiseをrejectし、これ以降の手順を中止する。
-
次の手順を並列で実行する。
-
device用の互換性のあるグラフィックスアダプターでリストア可能な描画バッファを待つ。
-
WebGLタスクソースで次の手順を実行するタスクをキューに入れる:
-
コンテキストをリストアし、device用の互換性のあるグラフィックスアダプター上で行う。
-
contextのXR compatibleブール値を
true
にする。 -
promiseをresolveする。
-
-
-
-
-
-
-
promiseを返す。
さらに、任意のWebGLコンテキストがロストしたときは、"webglcontextlost"イベントを発火する前に次の手順を実行する:
-
そのコンテキストのXR compatibleブール値を
false
にセットする。
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. イベント
本仕様でキューされるすべてのタスクソースは、特に指定がない限りXRタスクソースです。
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
で呼び出された場合、例外を投げなければなりません。
ユーザーエージェントが入力ソースイベントを発火する必要がある場合、名前name、XRFrame
frame、XRInputSource
sourceを用いて、次の手順を実行しなければなりません:
-
XRInputSourceEvent
eventを、type
name、frame
frame、inputSource
sourceで生成する。 -
frameのactiveブール値を
true
に設定する。 -
フレーム更新を適用する。
-
frameのactiveブール値を
false
に設定する。
12.3. XRInputSourcesChangeEvent
XRInputSourcesChangeEvent
は、
有効なXR入力ソースのリストの変化を通知するために、XRSession
に対して発火されます。
[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
に追加されたXRInputSource
のリストです。
removed
属性は、イベント発生時にXRSession
から削除されたXRInputSource
のリストです。
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
属性は、イベント後のreferenceSpace
の
ネイティブ原点の位置と姿勢を、イベント前の座標系で表します。この属性は、XRSystem
が新旧座標系間の差分を特定できない場合、null
となることがあります。
注記:
referenceSpace
やreferenceSpace
は、ヘッドセットが2つの異なる場所で着脱された場合などに該当します。このような場合、体験がワールドロックされたコンテンツに依存している場合は、ユーザーに警告し、シーンをリセットするべきです。
12.5. XRVisibilityMaskChangeEvent
由于视锥体并不总是与矩形显示器精确相交,XRLayer
的整个区域可能不会被显示。该事件将通知体验哪些 XRView
区域被展示给用户。
当用户代理需要告知体验 XRLayer
的显示区域发生变化时,会触发 XRVisibilityMaskChangeEvent
事件。
体验可以选择只绘制该区域,这有助于提升性能。
注意:体验必须在 requestSession
的 promise 解决期间注册该事件,否则事件可能会触发且遮罩信息会丢失。
[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
属性表示该遮罩所应用的 XREye
。
index
属性表示该遮罩应用到的 XRView
在 视图列表
中的偏移量。
vertices
属性是一个 列表,包含
X
、Y
坐标。体验必须假定 Z
坐标为 -1
。每组
X
、Y
、Z
坐标描述一个顶点。如果该数组为空,则应绘制 XRView
的整个区域。
indices
属性是一个 列表,用于描述 vertices
顶点列表中的索引。这些索引将描述该眼睛的 XRView
应绘制的区域。如果该数组为空,则应绘制 XRView
的整个区域。
该区域必须使用 projectionMatrix
(XRView
的 eye
)和默认
XRRigidTransform
进行绘制。
注意:这意味着该区域不得使用当前 XRView
的 XRRigidTransform
(eye
)进行绘制。
12.6. イベントタイプ
ユーザーエージェントは、以下の新しいイベントを必ず提供しなければなりません。イベントの登録および発火はDOMイベントの通常の挙動に従う必要があります。
ユーザーエージェントは、イベントを発火し、devicechange
という名前のイベントを XRSystem
オブジェクト上で発火しなければなりません。これは、イマーシブXRデバイス の利用可能性が変化したことを示します。ただし、ドキュメントの オリジン が "xr-spatial-tracking" パーミッションポリシー の利用を許可されていない場合は除きます。
ユーザーエージェントは、イベントを発火し、visibilitychange
という名前のイベントを XRSessionEvent
を使って
XRSession
上で、visibility state が変化するたびに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、end
という名前のイベントを XRSessionEvent
を使って
XRSession
上で、セッションがアプリケーションまたはユーザーエージェントによって終了したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、inputsourceschange
という名前のイベントを XRInputSourcesChangeEvent
を使って
XRSession
上で、セッションの list of active XR input sources が変化したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、trackedsourceschange
という名前のイベントを XRInputSourcesChangeEvent
を使って
XRSession
上で、セッションの list of active XR tracked sources
が変化したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、selectstart
という名前のイベントを XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary action
を開始したときに発火しなければなりません。イベントの型は . でなければなりません。
ユーザーエージェントは、イベントを発火し、selectend
という名前のイベントを XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary action
を終了したとき、または XRInputSource
が primary action
を開始した状態で切断されたときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、select
という名前のイベントを
XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary action
を完全に完了したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、squeezestart
という名前のイベントを XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary
squeeze action を開始したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、squeezeend
という名前のイベントを XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary
squeeze action を終了したとき、または XRInputSource
が primary
squeeze action を開始した状態で切断されたときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、squeeze
という名前のイベントを XRInputSourceEvent
を使って
XRSession
上で、その XRInputSource
のうち1つが primary
squeeze action を完全に完了したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、frameratechange
という名前のイベントを XRSessionEvent
を使って
XRSession
上で、XRコンポジタ が
XRSession
の
internal nominal framerate を変更したときに発火しなければなりません。
ユーザーエージェントは、イベントを発火し、reset
という名前のイベントを XRReferenceSpaceEvent
を使って
XRReferenceSpace
上で、native
origin または effective origin
の不連続が発生したとき(つまり、原点の位置または向きがユーザー環境に対して大きく変化した場合)に発火しなければなりません。(例:ユーザーがXRデバイスを再キャリブレーションした場合や、デバイスがトラッキングを失い再取得した場合など)reset
イベントは、boundsGeometry
が
XRBoundedReferenceSpace
で変更された場合にも必ず発火しなければなりません。
reset
イベントは、viewer のポーズが不連続になっただけで XRReferenceSpace
の原点の物理的対応付けが安定している場合(たとえば、viewer
が一時的にトラッキングを失い同じトラッキングエリアで再取得した場合など)は発火してはなりません。また、unbounded
参照空間が、ユーザーの近くで空間安定性を維持するために native origin
を少しずつ調整しても、大きな不連続が発生していない限りイベントは発火してはなりません。このイベントは新しい原点を使う XRアニメーションフレーム
の実行前に必ずディスパッチされる必要があります。reset
イベントが発火した参照空間の全てのオフセット参照空間にも reset
イベントを必ずディスパッチし、その boundsGeometry
も再計算されるべきです。
注: これはつまり、セッションは XRReferenceSpace
で reset
リスナーを持つものに対して強参照を保持する必要があることを意味します。
注: viewer の位置ジャンプは、アプリケーション側で emulatedPosition
ブール値を監視することで対処できます。もし viewer の位置ジャンプが emulatedPosition
が true
から false
に切り替わると同時に発生した場合、それは viewer
がトラッキングを再取得し、新しい位置がそれまでのエミュレート値から補正されたことを示します。「テレポート」機能のない体験では、これは通常アプリケーションが望む挙動です。しかし、体験に「テレポート」機能がある場合、トラッキング復帰時に
viewer
の位置を元に戻すのは不自然かもしれません。その場合、トラッキング復帰時には現在のVR空間内位置から再開し、そのジャンプ量をテレポートのオフセットに吸収するのがよいでしょう。そのためには、開発者は getOffsetReferenceSpace()
を呼び出して、effective origin を viewer の前フレームからのジャンプ分だけ調整した新しい参照空間を作成します。
13. セキュリティ、プライバシー、および快適性に関する考慮事項
WebXR Device APIは強力な新機能を提供しますが、それに伴い、ユーザーエージェントが対策を講じる必要がある、いくつかの独自のプライバシー、セキュリティ、快適性のリスクももたらします。
13.1. 機微な情報
XRの文脈において、機微な情報には、瞳孔間距離(IPD)などのユーザー設定可能なデータや、XRPose
のようなセンサーベースのデータなどが含まれますが、これらに限定されません。すべてのイマーシブセッションでは、ユーザーの姿勢情報が描画に必要なため、ある程度の機微なデータが公開されます。しかし、場合によっては、同じ機微な情報が"inline"
セッションを通じても公開されることがあります。
13.2. ユーザーの意図
ユーザーの意図とは、特定のアクションがユーザーの意思によるものであり、同意があることを示すユーザーからのシグナルです。
機微な情報を公開したり、ユーザー体験に大きな影響を与えるアクションを許可したりする前に、ユーザーの意図を確認する必要がある場合が多くあります。この意図は、さまざまな方法で伝達または観察されることがあります。
注記: ユーザーの意図を判断する一般的な方法は、UIコントロール(通常は「VRに入る」ボタン)の一時的なアクティベーションです。アクティベーションは一時的であるため、XRセッションを要求するブラウジングコンテキストは、UIコントロールを含むコンテキストの祖先または同一オリジンドメインの子孫であり、かつ最近アクティブドキュメントであった必要があります。
13.2.1. ユーザーアクティベーション
一時的なアクティベーションは、いくつかの状況でユーザーの意図の指標となる場合があります。13.2.2. ウェブアプリケーションの起動
一部の環境では、ページがアプリケーションとして表示され、イマーシブコンテンツを実行する明確な意図でインストールされる場合があります。その場合、ウェブアプリケーションの起動もユーザーの意図の指標となる場合があります。13.2.3. 暗黙的および明示的な同意
暗黙的な同意とは、ユーザーエージェントがユーザーに明示的に尋ねることなく、たとえばウェブアプリケーションのインストール状況、訪問頻度や直近の利用、またはユーザーがイマーシブ体験に入りたいという明確な意図を示すユーザーエージェント定義のアクションなどに基づいて、ユーザーの同意を判断する場合を指します。XRデータの機微性を考慮し、暗黙的なシグナルに依存する場合は十分な注意が必要です。
明示的な同意とは、ユーザーエージェントがユーザーに明確に尋ねた上で、ユーザーの同意を判断する場合を指します。明示的な同意を取得する際、ユーザーエージェントは何が要求されているかの説明を提示し、ユーザーに拒否する選択肢を提供します。ユーザーの同意を求めるリクエストは、保護される機能やユーザーエージェントの選択に応じて、さまざまな視覚的形式で提示できます。ウェブアプリケーションのインストール状況は、インストール時に何らかの明示的な同意が求められる場合、明示的な同意のシグナルと見なされることがあります。
13.2.4. 同意の有効期間
特定の明示的な同意が特定のオリジンに対して付与された場合、この同意はブラウジングコンテキストが終了するまで持続することが推奨されます。ユーザーエージェントは、ユーザーの意図の暗黙的または明示的なシグナルに基づいて、この同意の有効期間を延長または短縮することができますが、特に暗黙的なシグナルに依存する場合は、この推奨から逸脱する際には慎重に対応することが求められます。たとえば、イマーシブコンテンツを実行する明確な意図でインストールされたウェブアプリケーションの場合は、ユーザーの同意を持続させることが適切ですが、イマーシブコンテンツが副次的な機能である場合はそうではありません。
ユーザーエージェントがユーザーの同意をどれだけ持続させるかにかかわらず、機微な情報は、XRSession
が終了していない場合にのみ公開されなければなりません。
13.3. セッション中の同意
ユーザーエージェントが機能の利用に明示的な同意を求める原因となる、複数の非XR APIがあります。ユーザーエージェントがアクティブなイマーシブセッション中にユーザーの同意を求める場合、ユーザーエージェントは同意リクエストを表示する前に、必ずセッションを終了しなければなりません。機能に対するユーザーの同意がアクティブなイマーシブセッションの作成前にすでに付与されていた場合は、セッションを終了する必要はありません。
注記: この制限は、すべてのユーザーエージェント間で動作の一貫性を確保するためのものであり、ユーザーエージェントがセッション中の明示的な同意をどのように管理すべきかについて合意が得られるまでの暫定的な要件です。長期的な要件となることは想定されていません。
13.4. データ調整
場合によっては、データ調整(スロットリング、量子化、丸め、制限、またはその他の方法でXRデバイスから報告されるデータを操作すること)によって、セキュリティやプライバシー上の脅威を緩和できる場合があります。これは、ユーザーの意図が確立されている場合でも、フィンガープリント対策として必要になることがあります。ただし、データ調整による緩和策は、ユーザーの不快感を引き起こさない状況でのみ使用しなければなりません。
13.4.1. スロットリング
スロットリングとは、機微な情報が本来可能な頻度よりも低い頻度で報告されることを指します。この緩和策は、サイトがユーザーの意図や位置を推測したり、ユーザープロファイリングを行う能力を低減させる可能性があります。しかし、適切に使用しない場合、スロットリングはユーザーの不快感を引き起こす重大なリスクがあります。さらに、多くの状況では、完全な緩和策としては不十分な場合があります。13.4.2. 丸め、量子化、ファジング
丸め、量子化、ファジングは、本来開発者に返される生データを修正する3つの緩和策のカテゴリです。丸めは、データを表現する際の桁数を減らすことで精度を下げます。量子化は、連続的なデータを離散的な値のサブセットに制限します。ファジングは、データにわずかなランダム誤差を導入することです。これらの緩和策は、フィンガープリント対策として有効であり、特にユーザーの快適性に目立った影響を与えない場合に有用です。13.4.3. 制限
制限とは、データが特定の範囲内にある場合にのみ報告されることを指します。たとえば、ユーザーが承認された場所から特定の距離を超えて移動した場合に、位置姿勢データの報告を快適に制限することが可能です。この緩和策を採用する際は、ユーザー体験が損なわれないよう注意が必要です。範囲の終端で「ハードストップ」を避けることが望ましい場合が多く、これはユーザー体験を妨げる可能性があるためです。13.5. 保護された機能
APIによって公開される機微な情報は、脅威プロファイルやそれらの脅威に対する必要な保護策を共有するカテゴリに分類できます。
13.5.1. イマーシブ性
ユーザーはイマーシブセッションの作成タイミングを自分で制御できなければなりません。なぜなら、イマーシブセッションの作成はユーザーのマシンに侵襲的な変化をもたらすためです。たとえば、イマーシブセッションを開始すると、XRデバイスのセンサーが有効化され、デバイスのディスプレイへのアクセスが奪われ、イマーシブコンテンツの表示が始まり、他のアプリケーションによるXRハードウェアへのアクセスが終了する場合があります。また、一部のシステムでは大きな電力やパフォーマンスの負荷が発生したり、ステータストレイやストアフロントの起動がトリガーされることもあります。特定のglobal objectに対してイマーシブセッションリクエストが許可されるかどうかを判定するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
リクエストがglobal objectの一時的なアクティベーション中、またはウェブアプリケーションの起動時に行われていない場合、
false
を返す -
イマーシブセッションの開始に対するユーザーの意図が、明示的な同意または暗黙的な同意によって十分に理解されていない場合、
false
を返す -
true
を返す
"inline"
セッションの開始には同じ要件は自動的には適用されませんが、セッションの要求された機能によって追加の要件が課される場合があります。
特定のglobal objectに対してインラインセッションリクエストが許可されるかどうかを判定するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
セッションリクエストに必須機能またはオプション機能が含まれており、かつリクエストがglobal objectの一時的なアクティベーション中、またはウェブアプリケーションの起動時に行われていない場合、
false
を返す。 -
global objectが
Window
でない場合、false
を返す。 -
true
を返す。
13.5.2. ポーズ
センサーデータに基づく場合、XRPose
やXRViewerPose
は、入力スニッフィング、視線追跡、フィンガープリントなど、さまざまな方法で悪用される可能性のある機微な情報を公開します。
XRSession
sessionに対してポーズを報告できるかどうかを判定するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
sessionの関連グローバルオブジェクトが現在のグローバルオブジェクトでない場合、
false
を返す。 -
sessionの
visibilityState
がの場合、
false
を返す。 -
ポーズデータが返せるかどうかを次のように判定する:
注記: ポーズがフィンガープリント可能なデータを公開しないとユーザーエージェントが判断する方法は、ユーザーエージェントの裁量に委ねられます。
XRViewerPose
と XRPose
の主な違いは、XRView
情報が含まれている点です。
複数の view が存在し、かつそれらの物理的な関係がユーザーによって設定可能な場合、これらの view 間の関係はセンシティブな情報と見なされます。なぜなら、これはユーザーのフィンガープリントやプロファイリングに利用される可能性があるためです。
もし XRView
間の関係が XRデバイス
を一意に識別できる場合、ユーザーエージェントはフィンガープリント防止のため、XRView
データを匿名化しなければなりません。匿名化の方法はユーザーエージェントの裁量によります。
注: さらに、XRView
間の関係がユーザー設定の瞳孔間距離(IPD)によって影響を受ける場合は、ユーザーエージェントは 明示的な同意 をセッション作成時、いかなる XRView
データを報告する前に取得することが強く推奨されます。
13.5.3. リファレンス空間
使用されるリファレンス空間によって、アプリケーションに公開される機微な情報の種類が異なります。-
6DoFトラッキングをサポートするデバイスでは、
"local"
リファレンス空間を用いて歩行分析が可能となり、ユーザープロファイリングやフィンガープリントが行われる可能性があります。 -
6DoFトラッキングをサポートするデバイスでは、
"local-floor"
リファレンス空間を用いて歩行分析が可能となり、ユーザープロファイリングやフィンガープリントが行われる可能性があります。さらに、"local-floor"
リファレンス空間は床レベルが確立されているため、サイトがユーザーの身長を推測し、プロファイリングやフィンガープリントを行うことも可能です。 -
"bounded-floor"
リファレンス空間は、十分に制限されたサイズであれば開発者が地理的位置を特定することはできません。しかし、床レベルが確立されており、ユーザーが歩き回れるため、サイトがユーザーの身長を推測したり歩行分析を行うことでプロファイリングやフィンガープリントが可能です。また、バウンデッドリファレンス空間で報告される境界を使ってフィンガープリントが行われる可能性もあります。 -
"unbounded"
リファレンス空間は、最も多くの空間データを公開し、ユーザープロファイリングやフィンガープリントにつながる可能性があります。たとえば、このデータによりユーザーの地理的位置を特定したり、歩行分析を行うことが可能です。
そのため、さまざまなリファレンス空間タイプには、公開される機微な情報が安全に取り扱われるよう、作成に制限が設けられています:
ほとんどのリファレンス空間では、その利用に対するユーザーの意図が明示的な同意または暗黙的な同意によって十分に理解されている必要があります。詳細は機能要件の表を参照してください。
"local"
、
"local-floor"
、
"bounded-floor"
のいずれかのリファレンス空間が相互に関連付け可能な場合、それらは共通のネイティブ原点を共有しなければなりません。この制限は、"unbounded"
リファレンス空間の作成が制限されている場合にのみ適用されます。
2つの空間spaceとbaseSpace間でポーズを制限しなければならないかどうかを判定するには、ユーザーエージェントは次の手順を実行しなければなりません:
-
spaceまたはbaseSpaceのいずれかが
XRBoundedReferenceSpace
であり、もう一方の空間のネイティブ原点がネイティブ境界ジオメトリからユーザーエージェントが定める合理的な距離より外側にある場合、trueを返す。 -
spaceまたはbaseSpaceのいずれかが
XRReferenceSpace
であり、そのtypeが"local"
または"local-floor"
であり、両空間のネイティブ原点間の距離がユーザーエージェントが定める合理的な距離を超える場合、true
を返す。 -
false
を返す。
注記: ドキュメントの可視性要件は[DEVICE-ORIENTATION]に基づきます。
注記: "local"
または"local-floor"
リファレンス空間に対して報告されるポーズは、XRReferenceSpace
のネイティブ原点から15メートル以内に制限することが推奨されます。
注記: XRBoundedReferenceSpace
に対して報告されるポーズは、XRBoundedReferenceSpace
のネイティブ境界ジオメトリから1メートル外まで制限することが推奨されます。
13.6. 信頼された環境
信頼されたUIとは、ユーザーエージェントによって提示され、ユーザーが操作できるがページ側からは操作できないインターフェースです。ユーザーエージェントは信頼されたUIの表示をサポートしなければなりません。
信頼されたUIは、次の特性を持たなければなりません:
-
偽装できないこと
-
表示されるリクエストやコンテンツの発信元を示すこと
-
ユーザーとの共有シークレットに依存する場合、そのシークレットは複合現実キャプチャで観察できないこと(例: カメラで見えるジェスチャーではないこと)
-
同じUA内のイマーシブ体験間で一貫性があること
一般的に、信頼されたUIをサポートしたいユーザーエージェントには2つの選択肢があります。1つは信頼されたイマーシブUIで、これはイマーシブモードを終了しない信頼されたUIです。信頼されたイマーシブUIの実装は困難な場合があります。なぜならXRWebGLLayer
バッファがXRデバイスのディスプレイ全体を占有し、ユーザーエージェントが自身のためのピクセルを「予約」しないことが多いためです。ユーザーエージェントは信頼されたイマーシブUIをサポートする必要はなく、代わりに一時的にイマーシブモードを停止・終了し、非イマーシブな信頼されたUIをユーザーに表示しても構いません。
-
イマーシブモードでないときに表示されるデフォルトの2Dモードブラウザ
-
イマーシブモード内で表示され、偽装防止のために予約されたハードウェアボタンでのみ操作できるプロンプト
-
イマーシブセッションを一時停止し、プロンプトを表示できるネイティブなシステム環境を表示すること
入力情報(ヘッドポーズ、入力ポーズなど)を読み取る機能は、信頼されたUI
の完全性にリスクをもたらします。なぜなら、ページがこの情報を使って 信頼されたUI
でユーザーが行った選択を盗み見たり、キーボード入力を推測したりする可能性があるからです。このリスクを防ぐため、ユーザーエージェントは、ユーザーが 信頼されたUI(イマーシブか非イマーシブ、たとえばURLバーやシステムダイアログ)を操作している間、すべての XRSession
の
visibility state を
または
"visible-blurred"
に設定しなければなりません。さらに、悪意あるページが他のページの入力を監視できないようにするため、ユーザーエージェントは XRSession
の
visibility state を
に設定しなければなりません。これは、現在フォーカスされている領域 が、
XRSession
を作成したドキュメントに属していない場合です。
信頼されたUIの特定のインスタンスでと
"visible-blurred"
のどちらを使うか選択する際、ユーザーエージェントは頭部姿勢情報がセキュリティリスクとなるかどうかを考慮しなければなりません。たとえば、テキスト入力(特にパスワード入力)を含む信頼されたUIでは、入力中の頭部姿勢から入力内容が漏洩する可能性があります。このような場合、ユーザーエージェントは視線追跡関連情報の公開も停止すべきです。
ユーザーエージェントは権限プロンプトの表示に信頼されたUIを使用しなければなりません。
仮想環境がユーザーの頭部動作を低遅延かつ高フレームレートで一貫してトラッキングできない場合、ユーザーは混乱したり体調不良になる可能性があります。ページに一貫して高パフォーマンスかつ正しいコンテンツを強制することは不可能なため、ユーザーエージェントはトラッキングされた信頼された環境と、ページコンテンツとは非同期で動作するXRコンポジタを提供しなければなりません。コンポジタは信頼されたコンテンツと信頼されていないコンテンツの合成を担当します。コンテンツがパフォーマンス不足、フレーム未送信、または予期せず終了した場合でも、ユーザーエージェントは応答性の高い信頼されたUIの表示を継続できるべきです。
また、ページコンテンツはパフォーマンス以外の理由でもユーザーに不快感を与える可能性があります。トラッキングの誤用、点滅色、不快・恐怖・威圧を意図したコンテンツなどは、ユーザーが迅速にXR体験を終了したくなる原因となります。このような場合、XRデバイスを外すことが迅速または現実的でない場合もあります。これに対応するため、ユーザーエージェントは、予約されたハードウェアボタンの押下やジェスチャーなど、WebXRコンテンツから脱出してユーザーエージェントの信頼されたUIを表示するアクションをユーザーに提供しなければなりません。
13.7. コンテキスト分離
信頼されたUIは、ページで使用されるレンダリングコンテキスト(例: WebGLレンダリングコンテキスト)とは独立したレンダリングコンテキストによって描画され、その状態は分離されていなければなりません。これは、ページが信頼されたUIのコンテキストの状態を破壊し、トラッキング環境の正しい描画を妨げることを防ぐためです。また、ページが信頼されたUIの画像をキャプチャし、プライベート情報が漏洩する可能性も防ぎます。
さらに、CORS関連の脆弱性を防ぐため、各ブラウジングコンテキストはAPIから返されるオブジェクト(XRSession
など)の新しいインスタンスを参照します。context属性のように、ある関連レルムで設定されたXRWebGLLayer
は、同一オリジンでない別のXRWebGLLayer
から読み取ることはできません。同様に、APIで呼び出されるメソッドは他のブラウジングコンテキストに観測可能な状態変化を引き起こしてはなりません。例えば、システムレベルのオリエンテーションリセットを有効にするメソッドは公開されません。これは悪意のあるページが他のページのトラッキングを妨害するために繰り返し呼び出す可能性があるためです。ただし、ユーザーのジェスチャーやシステムメニューによるシステムレベルのオリエンテーションリセットはユーザーエージェントが尊重しなければなりません。
注記: これは、あるブラウジングコンテキストがイマーシブモードに入り、デバイスのロックを取得し、他のブラウジングコンテキストでdevicechangeイベントが発火するなど、状態変化が発生する場合には適用されません。
13.8. フィンガープリント
このAPIはユーザーが利用可能なハードウェアやその機能を記述するため、フィンガープリントのための追加の表面を必然的に提供します。完全に回避することは不可能ですが、ユーザーエージェントはこの問題を緩和するための措置を講じるべきです。本仕様では、利用可能なハードウェアの報告を常に1台のデバイスに限定しており、複数のヘッドセットが接続されているという稀なケースをフィンガープリントのシグナルとして利用できないようにしています。また、報告されるデバイスには文字列識別子がなく、XRSessionが作成されるまでデバイスの機能に関する情報もほとんど公開されません。XRSessionの作成時には機微な情報が公開されるため、追加の保護が必要です。
13.8.1. isSessionSupported()
のフィンガープリントに関する考慮
isSessionSupported()
はユーザーアクティベーションなしで呼び出せるため、フィンガープリントのベクトルとして利用される可能性があります。
"xr-session-supported"
は、強力な機能としてisSessionSupported()
APIへのアクセスを制御します。
"xr-session-supported"の権限関連アルゴリズムと型は次の通りです:
- permission descriptor type
-
dictionary
:XRSessionSupportedPermissionDescriptor PermissionDescriptor {XRSessionMode
; };mode name
forXRPermissionDescriptor
is "xr-session-supported"です。
13.8.2. "xr-session-supported"を自動的に付与する場合の考慮事項
Web上ではプライバシーとパーソナライズの間にしばしば緊張関係があります。このセクションでは、そのトレードオフをどこで制限できるか、またユーザーエージェントがisSessionSupported()
を通じてサイトにブラウザのWebXR機能をプライバシーを損なうことなく伝えられる場合について指針を示します。
"xr-session-supported"は、以下の基準に基づき一部のシステムで自動的に付与される場合があります。これによりユーザー体験が向上し、権限疲れを軽減できます。
ユーザーエージェントの集合が、すべて同じuserAgent
およびappVersion
を報告する場合、それらはユーザーエージェント文字列で区別できないといいます。こうしたクラスは通常、ブラウザのバージョンやプラットフォーム/デバイスによって特定されますが、接続された外部デバイスの状態では区別できません。ユーザーエージェント文字列で区別できないユーザーエージェントの概念を使うことで、フィンガープリントリスクを適切に評価できます。
一部のユーザーエージェント文字列で区別できないユーザーエージェントは、特定のXRSessionMode
のセッションを決してサポートしません。
例: モバイルARサポート要件を満たさないことが分かっている機種のスマートフォン上で動作するユーザーエージェント。この場合、isSessionSupported()
が常にXRSessionMode
がサポートされていないと報告しても、すべての該当デバイスが一貫して同じ値を返すため、フィンガープリントリスクはほとんどありません。また、デバイスの種類やモデルはuserAgent
など他の方法でも推測できると考えられます。したがって、このようなシステムでは、ユーザーエージェントは該当するXRSessionMode
に対して"xr-session-supported"を自動的に拒否すべきです。
他のユーザーエージェント文字列で区別できないユーザーエージェントは、特定のXRSessionMode
のセッションを通常サポートします。
例: VRヘッドセット内でのみ動作し、WebXRをサポートすることが分かっているユーザーエージェントは、ユーザーによって明示的にブロックされていない限り、"immersive-vr"
セッションをサポートする可能性が高い。この場合、XRSessionMode
がサポートされていないと報告することは、より一意な識別情報を与えることになります。そのため、XRSessionMode
が常に利用可能と報告され、requestSession()
が失敗する方がプライバシー保護につながり、ユーザーに混乱を与えることも少ないでしょう。このようなシステムでは、ユーザーエージェントは該当するXRSessionMode
に対して"xr-session-supported"を自動的に付与すべきです。
XR機能の可用性が非常に可変的なユーザーエージェント文字列で区別できないユーザーエージェント(例:
XR周辺機器をサポートするデスクトップシステム)は、最も高いフィンガープリントリスクを持ちます。このようなデバイス上のユーザーエージェントは、"xr-session-supported"を自動的に付与し、isSessionSupported()
APIが追加のフィンガープリント情報を提供することを許してはなりません。
-
isSessionSupported()
が呼ばれた際、明示的な同意(キャッシュされた権限プロンプト等も含む)を常に判定する。 -
"xr-session-supported"を自動的に付与するが、XRハードウェアやソフトウェアの有無にかかわらず、
isSessionSupported()
が常にtrue
を返すようにする。この場合、XRコンテンツを利用できないユーザーにも案内が表示されるためユーザー体験は低下する。 -
適切なハードウェアが存在する場合のみ
isSessionSupported()
が明示的な同意を要求し、ハードウェアが存在しない場合は適切にランダムな時間経過後にfalse
を返す。この場合、コンテンツはユーザーエージェントがXRハードウェアに接続されていない場合と、ユーザーが明示的な同意を拒否した場合を区別できてはならない。
どの手法を選択する場合でも、明示的な同意なしに接続されたXRハードウェアに関する追加情報を公開してはなりません。
14. 統合
14.1. Permissions Policy
この仕様は、空間トラッキングの利用を必要とするXRSession
がrequestSession()
で返されるかどうか、また空間トラッキングを必要とするセッションモードのサポートがisSessionSupported()
やdevicechange
イベントで示されるかどうかを制御するポリシー制御機能を定義します。
この機能の識別子は"xr-spatial-tracking"
です。
デフォルト許可リストは["self"]
です。
注記: ドキュメントのオリジンが"xr-spatial-tracking"
のpermissions policyの利用を許可されていない場合、すべてのイマーシブセッションはブロックされます。なぜなら、すべてのイマーシブセッションは空間トラッキングの利用を必要とするためです。インラインセッションは引き続き許可されますが、"viewer"
XRReferenceSpace
のみ利用可能に制限されます。
14.2. Permissions API統合
[permissions] APIは、ウェブサイトがユーザーに権限を要求したり、どの権限が付与されているかを照会したりするための統一的な方法を提供します。
"xr"
強力な機能の権限関連アルゴリズムと型は次の通りです:
- permission descriptor type
-
dictionary
:XRPermissionDescriptor PermissionDescriptor {XRSessionMode
;mode sequence <DOMString >
;requiredFeatures sequence <DOMString >
; };optionalFeatures name
forXRPermissionDescriptor
is "xr"です。 - permission result type
-
[
Exposed =Window ]interface
:XRPermissionStatus PermissionStatus {attribute FrozenArray <DOMString >
; };granted - permission query algorithm
-
"xr"パーミッションを
XRPermissionDescriptor
descriptorとXRPermissionStatus
statusで照会するには、UAは次の手順を実行しなければなりません:-
statusの
state
をdescriptorのpermission stateに設定する。 -
もしstatusの
state
が"denied"
なら、statusのgranted
を空のFrozenArray
に設定し、これ以降の手順を中止する。 -
resultを、descriptorの
requiredFeatures
、optionalFeatures
、mode
を使って要求された機能の解決を行った結果とする。 -
もしresultが
null
なら、次の手順を実行する:-
statusの
granted
を空のFrozenArray
に設定する。 -
これ以降の手順を中止する。
-
-
resultの各フィールド(consentRequired, consentOptional, granted)を取得する。
-
statusの
granted
をgrantedに設定する。 -
もしconsentRequiredとconsentOptionalがいずれも空なら、statusの
state
を"granted"
に設定し、これ以降の手順を中止する
-
- permission request algorithm
-
XRPermissionDescriptor
descriptorとXRPermissionStatus
statusで"xr"パーミッションをリクエストするには、UAは次の手順を実行しなければなりません:-
statusの
granted
を空のFrozenArray
に設定する。 -
requiredFeaturesをdescriptorの
requiredFeatures
とする。 -
optionalFeaturesをdescriptorの
optionalFeatures
とする。 -
deviceを、mode、requiredFeatures、optionalFeaturesで現在のデバイスの取得を行った結果とする。
-
resultを、requiredFeatures、optionalFeatures、
mode
で要求された機能の解決を行った結果とする。 -
もしresultが
null
なら、次の手順を実行する: -
resultの各フィールド(consentRequired, consentOptional, granted)を取得する。
-
UAはこの時点でconsentRequiredおよびconsentOptionalのいずれかの機能の利用についてユーザーの許可を求めてもよい。これらのプロンプトの結果は、これらの機能を有効にするユーザーの意図が明確かどうかの判定に含めるべきです。
-
consentRequired内の各featureについて次を実行する:
-
consentOptional内の各featureについて次を実行する:
-
statusの
granted
をgrantedに設定する。 -
すべてのgrantedの要素をdeviceの
set of granted features
(mode用)に追加する。
注記: UAは、ユーザーの意図が明確かどうかを判定する際、すべての要求機能について権限プロンプトをまとめて表示しても、1つずつ表示してもよいです。
注記: ウェブアプリケーションのユーザーの意図を判定する際、ユーザーエージェントは必ずユーザーによって明示的にウェブアプリケーションとして起動されたことを確認しなければなりません。単にオリジンがインストール済みウェブアプリケーションと一致するかどうかだけを確認してはなりません。
-
requiredFeaturesおよびoptionalFeatures、XRSessionMode
modeが与えられたときに要求された機能の解決を行うには、ユーザーエージェントは次の手順を実行しなければなりません:
-
device を mode、requiredFeatures、optionalFeatures に対して 現在のデバイスを取得する の結果とする。
-
previouslyEnabled を device の 許可された機能のセット(mode 用)とする。
-
もし device が
null
または device の サポートされているモードのリスト が mode を含まない 場合、次の手順を実行する:-
タプル (consentRequired, consentOptional, granted) を返す。
-
-
mode に紐づく デフォルト機能 テーブル内のすべての feature descriptor を granted に、未登録なら追加する。
-
requiredFeatures の各 feature について、次の手順を実行する:
-
もし feature が
null
なら、次のエントリに進む。 -
もし feature が有効な feature descriptor でなければ、
null
を返す。 -
もし feature が granted に既に含まれていれば、次のエントリに進む。
-
リクエストしているドキュメントの オリジン が、feature requirements テーブルで示される feature に必要な permissions policy のいずれかを許可されていない場合、
null
を返す。 -
もし session の XR device が feature で説明される機能をサポートできない、またはユーザーエージェントがその機能を拒否することを決定した場合、
null
を返す。 -
もし feature で説明される機能が 明示的な同意 を必要とし、feature が previouslyEnabled に含まれていなければ、consentRequired に追加する。
-
そうでなければ feature を granted に追加する。
-
-
optionalFeatures の各 feature について、次の手順を実行する:
-
もし feature が
null
なら、次のエントリに進む。 -
もし feature が有効な feature descriptor でなければ、次のエントリに進む。
-
もし feature が granted に既に含まれていれば、次のエントリに進む。
-
リクエストしているドキュメントの origin が feature requirements テーブルで示される feature に必要な permissions policy のいずれかを許可されていなければ、次のエントリに進む。
-
もし session の XR device が feature で説明される機能をサポートできない、またはユーザーエージェントがその機能を拒否した場合、次のエントリに進む。
-
もし feature で説明される機能が 明示的な同意 を必要とし、feature が previouslyEnabled に含まれていなければ、consentOptional に追加する。
-
そうでなければ feature を granted に追加する。
-
-
タプル
(|consentRequired|, |consentOptional|, |granted|)
を返す。
変更点
2022年3月31日 Candidate Recommendation Snapshot からの変更点
-
XRSessionのgranted featuresを公開 (GitHub #1296)
-
isSystemKeyboardSupported属性のサポートを追加 (GitHub #1314)
-
visibile-blurred時のgetPoseの挙動を明確化 (GitHub #1332)
-
Transient intentの追加 (GitHub #1343)
-
XRInputSourceに「他で可視である」ことを示すプロパティの初稿を追加 (GitHub #1353)
-
rgbとsrgbの挙動を明確化 (GitHub #1359)
2020年7月24日 Working Draft からの変更点
-
predictedDisplayTimeの修正とインライン動作の定義 (GitHub #1230)
-
XRFrame.predictedDisplayTimeを追加 (GitHub #1217)
-
targetFrameRateおよびsupportedFrameRatesのサポートを追加 (GitHub #1201)
-
foveationのサポートを追加 (
fixedFoveation
(GitHub #1195) -
セッションが明示的にリクエストした機能、またはモードに基づき暗黙的に付与された機能のみ利用可能に (GitHub #1189)
-
暗黙的なユーザー意図の例を強化 (GitHub #1188)
-
角速度・線形速度のサポートを追加 (GitHub #1182)
-
XRReferenceSpacesのプラットフォーム慣例の一貫性を確保 (GitHub #1180)
-
composition enabledフラグの反転 (composition enabled)(GitHub #1172)
-
既に終了したセッションでend()が呼ばれた場合はPromiseをreject (GitHub #1170)
-
requestAnimationFrame中にセッションが終了しているか検出 (GitHub #1169)
-
recommendedViewportScaleに量子化を要求 (GitHub #1151)
-
sessionsupported prefの自動付与を非規範化 (GitHub #1146)
-
非視覚的利用を含むXRデバイスの定義を追加 (GitHub #927)
-
最近のプライバシー議論の結論を反映 (GitHub #1124)
-
isSessionSupportedをユーザー意図からパーミッションベースに変更 (GitHub #1136)
-
最小viewport scaleが変化する可能性を明確化 (GitHub #1134)
-
フィンガープリント関連の改善 (GitHub #1133)
-
requestViewportScale/recommendedViewportScaleを追加 (GitHub #1132)
-
framebuffer scale factorが幅・高さそれぞれに適用されることを明確化 (GitHub #1131)
-
pending render stateが常に適用されることを保証 (GitHub #1128)
-
xr-spatial-tracking permissions policyでXR互換性を制御 (GitHub #1126)
-
updateRenderStateの適用タイミングを変更 (GitHub #1111)
2019年10月10日 Working Draft からの変更点
新機能:
-
セカンダリビュー機能の追加 (GitHub #1083)
-
XRRenderStateInitにlayers sequenceを追加 (GitHub #999)
-
入力ソースをprimary/auxiliaryに分割 (GitHub #929)
-
squeezeイベントの定義 (GitHub #893)
変更点:
-
Primary viewは常にアクティブでなければならない (GitHub #1105)
-
makeXRCompatible()でのコンテキストロスの正しい処理 (GitHub #1097)
-
active viewの概念を導入 (GitHub #1096)
-
frame/viewportキャッシュの明示的な扱い (GitHub #1093)
-
各種オブジェクトのキャッシュを許可 (GitHub #1088)
-
framebufferScaleFactorのclampを許可 (GitHub #1084)
-
「イマーシブデバイスの選択を保証する」アルゴリズムのスレッド性明確化、xrCompatibleの非推奨化 (GitHub #1081)
-
native originに関する事項の明確化 (GitHub #1071)
-
ドキュメントの可視性チェックをUAの選択に変更 (GitHub #1067)
-
check the layers stateアルゴリズムの追加 (GitHub #1064)
-
nullやエミュレートされたポーズに関する各種変更 (GitHub #1058)
-
XRInputSource/frameの入力フレームの意味付けを明記 (GitHub #1053)
-
XRRigidTransformのバリデーション追加 (GitHub #1043)
-
空のinput profile配列の扱いの微調整 (GitHub #1037)
-
trusted uiでvisible-blurred利用を許可し、テキスト入力漏洩への注意喚起を追加 (GitHub #1034)
-
window.rAF()に関する明確化 (GitHub #1033)
-
タスクやPromiseの扱いの整理 (GitHub #1032)
-
updateRenderState()でrender stateが渡されない場合の早期return (GitHub #1031)
-
responsible/active/focused documentの利用を削除 (GitHub #1030)
-
コンテキスト分離におけるbrowsing contextやrealmの扱い明確化 (GitHub #1029)
-
resetイベントがoffset spaceでも動作することを明記 (GitHub #1024)
-
各オブジェクトがどのrealmで生成されるか明示 (GitHub #1023)
-
rAF()コールバック引数に現在のタイムスタンプを使用 (GitHub #1015)
-
セッション機能リクエストにsessionパラメータ不要化 (GitHub #1012)
-
rAF内からrAFコールバックのキャンセルを許可 (GitHub #1005)
-
opaque framebufferが特定のセッションを参照することを明記 (GitHub #1004)
-
inputsourcechangeイベントの初回発火をPromise解決後に遅延 (GitHub #1002)
-
framebufferScaleFactorの効果を明記 (GitHub #993)
-
depth||stencilリクエスト時にdepth&&stencil結果を許可 (GitHub #987)
-
isSessionSupportedの返り値の柔軟性を向上 (GitHub #986)
-
インラインデバイス経由でのトラッキング/入力データ公開タイミングの明確化 (GitHub #985)
-
viewport形状への常識的な制限を追加 (GitHub #976)
-
preserveDrawingBufferがここでは効果を持たないことを明記 (GitHub #975)
-
インラインセッションのvisiblityStateの挙動を明確化 (GitHub #974)
-
opaque framebufferがdirtyと見なされる条件を定義 (GitHub #970)
-
デバイス変更時にインラインデバイスを更新する可能性を追加 (GitHub #947)
-
bounded reference spaceの挙動を明確化 (GitHub #938)
-
XR互換性アルゴリズムの複数修正 (GitHub #921)
-
trusted UIセクションの充実 (GitHub #875)
-
depthNearとdepthFarの使い方を明確化 (GitHub #888)
-
local-floor空間が推定身長を使う場合emulatedPositionがtrueにならないことを明記 (GitHub #871)
2019年2月5日 最初の公開ワーキングドラフト からの変更点
新機能:
-
XRInputSource->profiles(入力プロファイル名リスト)の追加 (GitHub #695)
-
XREye に none バリアントを追加 (GitHub #641)
-
明示的なインラインXRデバイスの追加 (GitHub #737)
-
データ調整と保護機能によるポーズのプライバシー配慮を追加 (GitHub #761)
-
リファレンススペースのプライバシー配慮を追加 (GitHub #762)
-
センシティブ情報とユーザー意図の定義を追加 (GitHub #757)
-
必須・オプション機能(機能依存性)の追加 (GitHub #749)
-
トラッキングロスとトラッキングリカバリーの追加 (GitHub #559)
-
blur/focus を visibilitychange に変更 (GitHub #687)
-
入力ソースのイベント順序の定義 (GitHub #629)
-
入力ソースリストの管理方法の記述 (GitHub #628)
-
origin offset を不変に (GitHub #612)
-
XRRenderState に inlineVerticalFieldOfView を追加 (GitHub #519)
-
Gamepad 連携の記述を追加 (GitHub #553)
-
XRWebGLLayer に ignoreDepthValues 属性を追加 (GitHub #548)
-
XRSpace XREnvironmentBlendMode.viewerSpace を追加 (GitHub #522)
-
XRPose および関連リファクタを仕様に追加 (GitHub #496)
削除された機能:
-
canvas inline を single に変更、XRPresentationContext を削除 (GitHub #656)
-
XRLayer 基底型の削除 (GitHub #688)
-
XRWebGLLayer.requestViewportScaling() の削除 (GitHub #631)
-
XRWebGLLayer から context 属性を削除 (GitHub #707)
-
要求値のみを反映する属性の削除 (GitHub #574)
-
XRSessionCreationOptions の削除 (GitHub #566)
変更点:
-
XRWebGLLayer のクリア動作要件を記述 (GitHub #866)
-
XRWebGLLayer フレームバッファは常にプリマルチプライドアルファを使用することを明記 (GitHub #840)
-
reset イベントの変換方向を明確化 (GitHub #843)
-
機能要件の満たし方を定義 (GitHub #839)
-
適切な場合はセッションがインラインかどうかを確認 (GitHub #834)
-
現時点でステレオインラインセッションを禁止 (GitHub #829)
-
projectionMatrix でデタッチされたバッファの扱いを追加 (GitHub #830)
-
makeXRCompatible() でイマーシブデバイスが選択されていることを保証 (GitHub #809)
-
features を 'any' のシーケンスに変更 (GitHub #807)
-
「fire an input source」アルゴリズムへのリンクとフレームの明示的構築 (GitHub #797)
-
Environment blend mode を仕様と explainer から削除 (GitHub #804)
-
各メソッドの説明を追加 (GitHub #798)
-
UAが手動デバイスアクティベーション手順を表示することを要求 (GitHub #799)
-
コンポジタの説明を明確化 (GitHub #805)
-
剛体変換の行列取得の数式を明確化 (GitHub #806)
-
UAがクリップ面を制約できるように (GitHub #802)
-
getViewport() で古い XRView の使用を禁止 (GitHub #796)
-
depth/alpha/stencil 値の利用方法を明記 (GitHub #800)
-
profiles 変更時に input source イベントを発火 (GitHub #795)
-
reset イベントの発火タイミングを明確化 (GitHub #637)
-
requestReferenceSpace() がクエリを拒否できる場合を明示 (GitHub #651)
-
XRRay.matrix をユニークにし、取得手順を追加 (GitHub #655)
-
Promise の返却に TAG 推奨事項を使用 (GitHub #700)
-
requestSession() の競合部分をメインスレッドに移動 (GitHub #706)
-
排他的アクセス時に小さなオーバーレイUIを許可することを明確化 (GitHub #709)
-
「end the session」と「shut down the session」を統合し、clarify、onend イベントを追加 (GitHub #710)
-
インラインセッションではXR互換フラグをチェックしない (GitHub #705)
-
position DOMPointInit のバリデーション (GitHub #568)
-
ネイティブオリジンの明示的な仕様化 (GitHub #621)
-
buttonIndex の削除 (GitHub #741)
-
"immersive-ar" と XRRay への参照を削除 (GitHub #784)
-
XRInputSource.gamepad への参照を explainer と index.bs から削除 (GitHub #782)
-
無効な view で getViewport を呼ぶとエラーを投げるように (GitHub #771)
-
セッション中の同意リクエストをブロック (GitHub #767)
-
XRPresentationContext の仕様化 (GitHub #501)
-
inputSources getter をメソッドから属性に変更 (GitHub #624)
-
必須 gamepad index を -1 に変更 (GitHub #690)
-
デタッチされた配列の扱いを追加 (GitHub #684)
-
センシティブUIがWebXRコンテンツを隠すことを要求 (GitHub #742)
-
xr-standard gamepad マッピングをより厳格に (GitHub #735)
-
XRRay.matrix の計算アルゴリズム修正 (GitHub #728)
-
XRRay.matrix アルゴリズムでデタッチ配列を修正 (GitHub #716)
-
requestSession() で未対応モードの扱いを簡素化 (GitHub #714)
-
XRRenderState の明確化 (GitHub #703)
-
'list of pending render states' を 'pending render state' に置換 (GitHub #701)
-
gamepad プレースホルダーボタン・軸の定義を明確化 (GitHub #661)
-
タッチパッドがタッチされていない場合の値を明確化 (GitHub #660)
-
getPose の引数 referenceSpace→baseSpace にリネーム (GitHub #659)
-
変換の乗算順序を修正 (GitHub #649)
-
local および local-floor トラッキングの前提を明確化 (GitHub #648)
-
利用可能なスペースの簡素化 (GitHub #626)
-
requestSession: まずユーザーアクティベーションを確認 (GitHub #685)
-
boundsGeometry を effective origin 相対で動作させるように (GitHub #613)
-
views 配列の構築方法を明示 (GitHub #614)
-
Gamepad id が unknown となるケースを特定 (GitHub #615)
-
XRSpace, get(Viewer)Pose 定義の大幅見直し (GitHub #609)
-
supportsSessionMode を supportsSession にリネーム (GitHub #595)
-
リファレンススペース型とインターフェースの統合 (GitHub #587)
-
inverse 属性は常に同じオブジェクトを返すように (GitHub #586)
-
セッション終了時に未解決のPromiseを拒否 (GitHub #585)
-
projection matrix に shear を含めてもよいことを明記 (GitHub #575)
-
updateRenderState が投げる例外の記述 (GitHub #511)
-
requestSession()・セッション初期化の編集 (GitHub #601)
-
XRRigidTransform inverse をメソッドから属性に変更 (GitHub #560)
-
合成時にdepth値を利用していることを明示 (GitHub #563)
-
Stationary サブタイプのサポートは all-or-nothing に (GitHub #537)
-
outputContext を XRRenderState に移動 (GitHub #536)
-
getViewerPose は非rAF XRFrameでエラーを投げることを明記 (GitHub #535)
-
viewMatrix を削除し XRTransform.inverse() を追加 (GitHub #531)
-
XRHandedness enum を '' から 'none' に変更 (GitHub #526)
-
tracked-pointer ray の推奨エルゴノミクスを明記 (GitHub #524)
-
XRRay コンストラクタの明確化と正規化の定義 (GitHub #521)
-
identity reference space の仕様文を追加 (GitHub #520)
-
イマーシブセッションが拒否されるタイミングを明確化 (GitHub #360)
-
base layer がない場合はフレームコールバックを呼ばないことを明記 (GitHub #512)
15. 謝辞
WebXR Device API仕様への貢献に感謝します(敬称略):
また、このプロジェクトを始動させてくれた Vladimir Vukicevic (Unity) に特別な感謝を捧げます!