From 77d9cc56219f6116f4de31ca729dded113ade28b Mon Sep 17 00:00:00 2001 From: Nell Waliczek Date: Tue, 25 Jun 2019 19:10:23 -0700 Subject: [PATCH 1/5] Enable optional/required features to be checked before session creation --- explainer.md | 86 +++++++++++++++++++++++++---------- spatial-tracking-explainer.md | 26 ++++++++++- 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/explainer.md b/explainer.md index 609b0c44..5eeb9784 100644 --- a/explainer.md +++ b/explainer.md @@ -137,7 +137,7 @@ function beginXRSession() { } ``` -In this sample, the `beginXRSession` function, which is assumed to be run by clicking the "Enter VR" button in the previous sample, requests an `XRSession` that operates in `immersive-vr` mode. The `requestSession` method returns a promise that resolves to an `XRSession` upon success. When requesting a session, the capabilities that the returned session must have, including it's XR mode, are passed in via an `XRSessionCreationOptions` dictionary. +In this sample, the `beginXRSession` function, which is assumed to be run by clicking the "Enter VR" button in the previous sample, requests an `XRSession` that operates in `immersive-vr` mode. The `requestSession` method returns a promise that resolves to an `XRSession` upon success. In addition to the `XRSessionMode`, developers may supply an `XRSessionInit` dictionary containing the capabilities that the returned session must have. For more information, see [Feature dependencies](#feature-dependencies). If `supportsSession` resolved for a given mode, then requesting a session with the same mode should be reasonably expected to succeed, barring external factors (such as `requestSession` not being called in a user activation event for an immersive session.) The UA is ultimately responsible for determining if it can honor the request. @@ -373,21 +373,9 @@ The UA may choose to present the immersive AR session's content via any type of ## Inline sessions -There are several scenarios where it's beneficial to render a scene whose view is controlled by device tracking within a 2D page. For example: +When authoring content to be viewed immersively, it may be beneficial to use an `inline` session to view the same content in a 2D browser window. Using an inline session enables content to use a single rendering path for both inline and immersive presentation modes. It also makes switching between inline content and immersive presentation of that content easier. - - Using phone rotation to view panoramic content. - - Taking advantage of 6DoF tracking on devices with no associated headset, like [ARCore](https://developers.google.com/ar/) or [ARKit](https://developer.apple.com/arkit/) enabled phones. - - Making use of head-tracking features for devices like [zSpace](http://zspace.com/) systems. - -These scenarios can make use of inline sessions to render tracked content to the page. Using an inline session also enables content to use a single rendering path for both inline and immersive presentation modes. It also makes switching between inline content and immersive presentation of that content easier. - -The [`RelativeOrientationSensor`](https://w3c.github.io/orientation-sensor/#relativeorientationsensor) and [`AbsoluteOrientationSensor`](https://w3c.github.io/orientation-sensor/#absoluteorientationsensor) interfaces (see [Motion Sensors Explainer](https://w3c.github.io/motion-sensors/)) can be used to polyfill the first case. - -`XRWebGLLayer` created with an `inline` session will not allocate a new WebGL framebuffer but instead set the `framebuffer` attribute to `null`. That way when `framebuffer` is bound all WebGL commands will naturally execute against the WebGL context's default framebuffer and display on the page like any other WebGL content. When that layer is set as the `XRRenderState`'s `baseLayer` the inline session is able to render it's output to the page. - -Immersive and inline sessions may run their render loops at at different rates. During immersive sessions the UA runs the rendering loop at the XR device's native refresh rate. During inline sessions the UA runs the rendering loop at the refresh rate of page (aligned with `window.requestAnimationFrame`.) The method of computation of `XRView` projection and view matrices also differs between immersive and inline sessions, with inline sessions taking into account the output canvas dimensions and possibly the position of the users head in relation to the canvas if that can be determined. - -UAs may have different restrictions on inline sessions that don't apply to immersive sessions. For instance, the UA does not have to guarantee the availability of tracking data to inline sessions, and even when it does a different set of `XRReferenceSpace` types may be available to inline sessions versus immersive sessions. +A `XRWebGLLayer` created with an `inline` session will not allocate a new WebGL framebuffer but instead set the `framebuffer` attribute to `null`. That way when `framebuffer` is bound all WebGL commands will naturally execute against the WebGL context's default framebuffer and display on the page like any other WebGL content. When that layer is set as the `XRRenderState`'s `baseLayer` the inline session is able to render it's output to the page. ```js function beginInlineXRSession() { @@ -405,20 +393,67 @@ function beginInlineXRSession() { } ``` -The UA should not reject requests for an inline session unless the page's feature policy prevents it. `navigator.xr.supportsSession()` can still be used if a page wants to test if inline session are allowed. +Immersive and inline sessions may run their render loops at at different rates. During immersive sessions the UA runs the rendering loop at the XR device's native refresh rate. During inline sessions the UA runs the rendering loop at the refresh rate of page (aligned with `window.requestAnimationFrame`.) The method of computation of `XRView` projection and view matrices also differs between immersive and inline sessions, with inline sessions taking into account the output canvas dimensions and possibly the position of the users head in relation to the canvas if that can be determined. + +`navigator.xr.supportsSession()` will always return `true` when checking the support of `"inline"` sessions. The UA should not reject requests for an inline session unless the page's feature policy prevents it or unless a required feature is unavailable as described in [Feature dependencies](#feature-dependencies)). For example, the following use cases all depend on additional reference space types which would need to be enabled via the `XRSessionInit`: + - Using phone rotation to view panoramic content. + - Taking advantage of 6DoF tracking on devices with no associated headset, like [ARCore](https://developers.google.com/ar/) or [ARKit](https://developer.apple.com/arkit/) enabled phones. (Note that this is not the same as `immersive-ar` as it does not provide automatic camera composition) + - Making use of head-tracking features for devices like [zSpace](http://zspace.com/) systems. + +## Advanced functionality + +Beyond the core APIs described above, the WebXR Device API also exposes several options for taking greater advantage of the XR hardware's capabilities. + +### Feature dependencies +Once developers have mastered session creation and rendering, they will often be interested in using additional WebXR features that may not be universally available. While developers are generally encouraged to design for progressive enhancement, some experiences may have requirements on features that are not guaranteed to be universally available. For example, a guided tour would not function on an Oculus Go because it is unable to provide an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space). If an experience is completely unusable without a specific feature, it would be a poor user experience to initialize the underlying XR platform and create a session only to immediately notify the user it won't work. + +Features may be unavailable for a number of reasons, among which is the fact not all devices which support WebXR can support the full set of features. Another consideration is that some features expose [sensitive information](privacy-security-explainer.md#sensitive-information) which may require a clear signal of [user intent](privacy-security-explainer.md#user-intent) before functioning. Any feature which requires this signal to be provided via [explicit consent](privacy-security-explainer.md#explicit-consent) must request this consent prior to the session being created. This ensures a consistent experience across all hardware form-factors, regardless of whether the UA has a [trusted immersive UI](privacy-security-explainer.md#trusted-immersive-ui) available. + +WebXR allows the following features to be requested: +* `local` +* `local-floor` +* `bounded-floor` +* `unbounded` + +This list is currently limited to a subset of reference space types, but in the future will expand to include additional features. Some potential future features under discussion that would be candidates for this list are: eye tracking, plane detection, geo alignment, etc. + +Developers communicate their feature requirements by categorizing them into one of the following groups: +* **Required** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device or if the UA determines the user does not wish the feature enabled. +* **Optional** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. + +Features recognized by the UA that are not explicitly listed in these arrays will be implicitly added to `XRSessionInit.optionalFeatures` if they do not require consent or [consent has been implied](privacy-security-explainer.md#implied-consent). For example, creating an `immersive-vr` session implies consent for `local` and `local-floor` reference spaces even if not explicitly listed in `XRSessionInit`. If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. + +The following sample code represents the likely behavior of the guided tour example above. It depends on having an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space) and will reject creating the session if not available. ```js -function checkInlineSupport() { - // Check to see if the page is allowed to request inline sessions. - return navigator.xr.supportsSession('inline') - .then(() => { console.log("Inline content is supported!"); }) - .catch((reason) => { console.log("Inline content is blocked: " + reason); }); +function onEnterARClick() { + navigator.xr.requestSession('immersive-ar', { + requiredFeatures: [ 'unbounded' ] + }) + .then(onSessionStarted) + .catch(() => { + // Display message to the user explaining that the experience could not + // be started. + }); } ``` -## Advanced functionality +The following sample code shows an inline experience that would prefer to use motion tracking if available, but will fall back to using touch/mouse input if not. -Beyond the core APIs described above, the WebXR Device API also exposes several options for taking greater advantage of the XR hardware's capabilities. +```js +navigator.xr.requestSession('inline', { + optionalFeatures: [ 'local' ] +}) +.then(onSessionStarted); + +function onSessionStarted(session) { + session.requestReferenceSpace('local') + .then(onLocalReferenceSpaceCreated) + .catch(() => { + session.requestReferenceSpace('viewer').then(onViewerReferenceSpaceCreated); + }); +} +``` ### Controlling rendering quality @@ -580,6 +615,11 @@ enum XRSessionMode { "immersive-ar" } +dictionary XRSessionInit { + sequence requiredFeatures; + sequence optionalFeatures; +} + [SecureContext, Exposed=Window] interface XRSession : EventTarget { readonly attribute XREnvironmentBlendMode environmentBlendMode; readonly attribute XRRenderState renderState; diff --git a/spatial-tracking-explainer.md b/spatial-tracking-explainer.md index 6fdc3ea0..9c9e68c3 100644 --- a/spatial-tracking-explainer.md +++ b/spatial-tracking-explainer.md @@ -310,6 +310,14 @@ Immersive sessions will always be able to provide `viewer`, `local`, and `local- let xrSession = null; let xrReferenceSpace = null; +function onButtonClick() { + navigator.xr.requestSession('immersive-vr', { optionalFeatures: ['bounded-floor'] }) + .then(onSessionStarted) + .catch(err => { + window.requestAnimationFrame(onDrawFrame); + }); +} + function onSessionStarted(session) { xrSession = session; // First request an bounded-floor frame of reference. @@ -329,7 +337,23 @@ function onSessionStarted(session) { } ``` -### Floor alignment +While many sites will be able to provide this fallback, for some sites this will not be possible. Under these circumstances, it is instead preferable for session creation to reject rather than spin up immersive display/tracking systems only to immediately exit the session. To make session creation contingent on support for a specific reference space types, add them to `XRSessionInit.requiredFeatures`. For more information, see [Feature dependencies](explainer.md#feature-dependencies) + +```js +let xrSession = null; +let xrReferenceSpace = null; + +function beginXRSession() { + navigator.xr.requestSession('immersive-ar', { requiredFeatures: ['unbounded'] }) + .then(onSessionStarted) + .catch(err => { + // Display message to the user explaining that the experience could not + // be started. + }); +} +``` + +### Floor Alignment Some XR hardware with inside-out tracking has users establish "known spaces" that can be used to easily provide `bounded-floor` and `local-floor` reference spaces. On inside-out XR hardware which does not intrinsically provide these known spaces, the User Agent must still provide `local-floor` reference spaces. It may do so by estimating a floor level, but may not present any UI at the time the reference space is requested. Additionally, XR hardware with orientation-only tracking may also provide an emulated value for the floor offset of a `local-floor` reference space. On these devices, it is recommended that the User Agent or underlying platform provide a setting for users to customize this value. From 76e2e37a62137efa4268a55d46cb54bf3eb22e2e Mon Sep 17 00:00:00 2001 From: Nell Waliczek Date: Wed, 26 Jun 2019 14:17:27 -0700 Subject: [PATCH 2/5] Addressing Brandon's feed back --- explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/explainer.md b/explainer.md index 5eeb9784..167e54ab 100644 --- a/explainer.md +++ b/explainer.md @@ -405,7 +405,7 @@ Immersive and inline sessions may run their render loops at at different rates. Beyond the core APIs described above, the WebXR Device API also exposes several options for taking greater advantage of the XR hardware's capabilities. ### Feature dependencies -Once developers have mastered session creation and rendering, they will often be interested in using additional WebXR features that may not be universally available. While developers are generally encouraged to design for progressive enhancement, some experiences may have requirements on features that are not guaranteed to be universally available. For example, a guided tour would not function on an Oculus Go because it is unable to provide an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space). If an experience is completely unusable without a specific feature, it would be a poor user experience to initialize the underlying XR platform and create a session only to immediately notify the user it won't work. +Once developers have mastered session creation and rendering, they will often be interested in using additional WebXR features that may not be universally available. While developers are generally encouraged to design for progressive enhancement, some experiences may have requirements on features that are not guaranteed to be universally available. For example, an experience which requires users to move around a large physical space, such as a guided tour, would not function on an Oculus Go because it is unable to provide an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space). If an experience is completely unusable without a specific feature, it would be a poor user experience to initialize the underlying XR platform and create a session only to immediately notify the user it won't work. Features may be unavailable for a number of reasons, among which is the fact not all devices which support WebXR can support the full set of features. Another consideration is that some features expose [sensitive information](privacy-security-explainer.md#sensitive-information) which may require a clear signal of [user intent](privacy-security-explainer.md#user-intent) before functioning. Any feature which requires this signal to be provided via [explicit consent](privacy-security-explainer.md#explicit-consent) must request this consent prior to the session being created. This ensures a consistent experience across all hardware form-factors, regardless of whether the UA has a [trusted immersive UI](privacy-security-explainer.md#trusted-immersive-ui) available. From 6deb5203973479648ff81093779ae3507ba9f824 Mon Sep 17 00:00:00 2001 From: Nell Waliczek Date: Wed, 26 Jun 2019 14:32:13 -0700 Subject: [PATCH 3/5] More Brandon feedback --- explainer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/explainer.md b/explainer.md index 167e54ab..048268e1 100644 --- a/explainer.md +++ b/explainer.md @@ -421,7 +421,7 @@ Developers communicate their feature requirements by categorizing them into one * **Required** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device or if the UA determines the user does not wish the feature enabled. * **Optional** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. -Features recognized by the UA that are not explicitly listed in these arrays will be implicitly added to `XRSessionInit.optionalFeatures` if they do not require consent or [consent has been implied](privacy-security-explainer.md#implied-consent). For example, creating an `immersive-vr` session implies consent for `local` and `local-floor` reference spaces even if not explicitly listed in `XRSessionInit`. If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. +If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. Under some circumstances, features recognized by the UA but not explicitly listed in these arrays may be implicitly added to `XRSessionInit.optionalFeatures`. For example, if a feature does not require a signal of [user intent](privacy-security-explainer.md#user-intent). Or, if the requested session mode implies consent, such as `immersive-vr` does for `local` and `local-floor` reference spaces. The following sample code represents the likely behavior of the guided tour example above. It depends on having an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space) and will reject creating the session if not available. From 4f033b66c8610a9e8ad55a6ef5a986764d331e30 Mon Sep 17 00:00:00 2001 From: Nell Waliczek Date: Mon, 1 Jul 2019 10:13:24 -0700 Subject: [PATCH 4/5] Cleans up language around which features can be enabled by default --- explainer.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/explainer.md b/explainer.md index 048268e1..7766f8f4 100644 --- a/explainer.md +++ b/explainer.md @@ -421,7 +421,10 @@ Developers communicate their feature requirements by categorizing them into one * **Required** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device or if the UA determines the user does not wish the feature enabled. * **Optional** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. -If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. Under some circumstances, features recognized by the UA but not explicitly listed in these arrays may be implicitly added to `XRSessionInit.optionalFeatures`. For example, if a feature does not require a signal of [user intent](privacy-security-explainer.md#user-intent). Or, if the requested session mode implies consent, such as `immersive-vr` does for `local` and `local-floor` reference spaces. +If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. Some features recognized by the UA but not explicitly listed in these arrays may be enabled by default for a session. This is only allowed if the feature does not require a signal of [user intent](privacy-security-explainer.md#user-intent) nor impact performance or the behavior of other features when enabled. At this time, only the following features may be enabled by default: +| Feature | Circumstances | +| ------ | ------- | +| `local` | Successfully created session of mode `immersive-ar` or `immersive-vr` | The following sample code represents the likely behavior of the guided tour example above. It depends on having an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space) and will reject creating the session if not available. From 3a997b7058e8eda5ac3f4ce565762795827ca10d Mon Sep 17 00:00:00 2001 From: Nell Waliczek Date: Mon, 1 Jul 2019 16:56:08 -0700 Subject: [PATCH 5/5] Addressing (hopefully) the last feedback --- explainer.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/explainer.md b/explainer.md index 7766f8f4..41375e88 100644 --- a/explainer.md +++ b/explainer.md @@ -417,14 +417,11 @@ WebXR allows the following features to be requested: This list is currently limited to a subset of reference space types, but in the future will expand to include additional features. Some potential future features under discussion that would be candidates for this list are: eye tracking, plane detection, geo alignment, etc. -Developers communicate their feature requirements by categorizing them into one of the following groups: -* **Required** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device or if the UA determines the user does not wish the feature enabled. -* **Optional** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. +Developers communicate their feature requirements by categorizing them into one of the following sequences in the `XRSessionInit` that can be passed into `xr.requestSession()`: +* **`requiredFeatures`** This feature must be available in order for the experience to function at all. If [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. Session creation will be rejected if the feature is unavailable for the XR device, if the UA determines the user does not wish the feature enabled, or if the UA does not recognize the feature being requested. +* **`optionalFeatures`** The experience would like to use this feature for the entire session, but can function without it. Again, if [explicit consent](privacy-security-explainer.md#explicit-consent) is necessary, users will be prompted in response to `xr.requestSession()`. However, session creation will succeed regardless of the feature's hardware support or user intent. Developers must not assume optional features are available in the session and check the result from attempting to use them. -If the UA does not recognize an entry in `XRSession.requiredFeatures` the session will not be created. Some features recognized by the UA but not explicitly listed in these arrays may be enabled by default for a session. This is only allowed if the feature does not require a signal of [user intent](privacy-security-explainer.md#user-intent) nor impact performance or the behavior of other features when enabled. At this time, only the following features may be enabled by default: -| Feature | Circumstances | -| ------ | ------- | -| `local` | Successfully created session of mode `immersive-ar` or `immersive-vr` | +(NOTE: `xr.supportsSession()` does not accept an `XRSessionInit` parameter and supplying one will have no effect) The following sample code represents the likely behavior of the guided tour example above. It depends on having an [`unbounded` reference space](spatial-tracking-explainer.md#unbounded-reference-space) and will reject creating the session if not available. @@ -458,6 +455,11 @@ function onSessionStarted(session) { } ``` +Some features recognized by the UA but not explicitly listed in these arrays will be enabled by default for a session. This is only done if the feature does not require a signal of [user intent](privacy-security-explainer.md#user-intent) nor impact performance or the behavior of other features when enabled. At this time, only the following features will be enabled by default: +| Feature | Circumstances | +| ------ | ------- | +| `local` | Successfully created session of mode `immersive-ar` or `immersive-vr` | + ### Controlling rendering quality While in immersive sessions, the UA is responsible for providing a framebuffer that is correctly optimized for presentation to the `XRSession` in each `XRFrame`. Developers can optionally request the framebuffer size be scaled, though the UA may not respect the request. Even when the UA honors the scaling requests, the result is not guaranteed to be the exact percentage requested. @@ -602,10 +604,15 @@ partial interface Navigator { readonly attribute XR xr; }; +dictionary XRSessionInit { + sequence requiredFeatures; + sequence optionalFeatures; +} + [SecureContext, Exposed=Window] interface XR : EventTarget { attribute EventHandler ondevicechange; Promise supportsSession(XRSessionMode mode); - Promise requestSession(XRSessionMode mode); + Promise requestSession(XRSessionMode mode, optional XRSessionInit); }; // @@ -618,11 +625,6 @@ enum XRSessionMode { "immersive-ar" } -dictionary XRSessionInit { - sequence requiredFeatures; - sequence optionalFeatures; -} - [SecureContext, Exposed=Window] interface XRSession : EventTarget { readonly attribute XREnvironmentBlendMode environmentBlendMode; readonly attribute XRRenderState renderState;