Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions files/en-us/web/api/webxr_device_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ The equipment may also include an accelerometer, barometer, or other sensors whi

- {{DOMxRef("XRView")}}
- {{DOMxRef("XRViewport")}}
- {{DOMxRef("XRVisibilityMaskChangeEvent")}}

### Geometric primitives

Expand Down
4 changes: 3 additions & 1 deletion files/en-us/web/api/xrsession/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ browser-compat: api.XRSession

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}{{SeeCompatTable}}

The **`XRSession`** interface of the [WebXR Device API](/en-US/docs/Web/API/WebXR_Device_API) represents an ongoing XR session, providing methods and properties used to interact with and control the session. To open a WebXR session, use the {{domxref("XRSystem")}} interface's {{domxref("XRSystem.requestSession", "requestSession()")}} method.
The **`XRSession`** interface of the [WebXR Device API](/en-US/docs/Web/API/WebXR_Device_API) represents an ongoing session between a web application and a user's XR device (such as a VR headset), providing methods and properties used to interact with and control the session. To open a WebXR session, use the {{domxref("XRSystem")}} interface's {{domxref("XRSystem.requestSession", "requestSession()")}} method.

With `XRSession` methods, you can poll the viewer's position and orientation (the {{domxref("XRViewerPose")}}), gather information about the user's environment, and present imagery to the user. `XRSession` supports both inline and immersive virtual and augmented reality modes.

Expand Down Expand Up @@ -83,6 +83,8 @@ _The following events are delivered to `XRSession` objects._
- : An event of type {{domxref("XRInputSourceEvent")}} which is sent to the `XRSession` when the user initially squeezes a squeezable controller. This may be, for example, a trigger which is used to represent grabbing objects, or might represent actual squeezing when wearing a haptic glove. Also available through the `onsqueezestart` event handler property.
- {{domxref("XRSession.visibilitychange_event", "visibilitychange")}} {{Experimental_Inline}}
- : An {{domxref("XRSessionEvent")}} which is sent to the session when its visibility state as indicated by the {{domxref("XRSession.visibilityState", "visibilityState")}} changes. Also available through the `onvisibilitychange` event handler property.
- {{domxref("XRSession.visibilitymaskchange_event", "visibilitymaskchange")}} {{Experimental_Inline}}
- : An {{domxref("XRVisibilityMaskChangeEvent")}} which is sent to the session when the portion of the {{domxref("XRView")}} visible to the user changes, enabling performance improvements by allowing the browser to draw only the visible part of the updated view. Also available through the `onvisibilitymaskchange` event handler property.

## Example

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: "XRSession: visibilitymaskchange event"
short-title: visibilitymaskchange
slug: Web/API/XRSession/visibilitymaskchange_event
page-type: web-api-event
status:
- experimental
browser-compat: api.XRSession.visibilitymaskchange_event
---

{{APIRef("WebXR Device API")}}{{SeeCompatTable}}{{SecureContext_Header}}

The **`visibilitymaskchange`** event is sent to an {{domxref("XRSession")}} when the portion of an {{domxref("XRView")}} visible to the user changes.

Note that the view is associated with a particular eye, and the part that is visible to the user is defined by a visibility mask. For more information see the {{domxref("XRVisibilityMaskChangeEvent")}} interface.

This enables performance improvements by allowing the browser to draw only the visible part of the updated view.

## Syntax

Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property.

```js-nolint
addEventListener("visibilitymaskchange", (event) => { })

onvisibilitymaskchange = (event) => { }
```

## Event type

An {{domxref("XRVisibilityMaskChangeEvent")}}. Inherits from {{domxref("Event")}}.

{{InheritanceDiagram("XRVisibilityMaskChangeEvent")}}

## Event properties
Comment thread
hamishwillee marked this conversation as resolved.

_In addition to the properties listed below, properties from the parent interface, {{domxref("Event")}}, are available._

- {{domxref("XRVisibilityMaskChangeEvent.eye", "eye")}} {{ReadOnlyInline}}
- : The eye the mask applies to.
- {{domxref("XRVisibilityMaskChangeEvent.index", "index")}} {{ReadOnlyInline}}
- : The index of the current {{domxref("XRView")}} in the {{domxref("XRViewerPose.views")}} array.
- {{domxref("XRVisibilityMaskChangeEvent.indices", "indices")}} {{ReadOnlyInline}}
- : An array of indices specifying the vertices in the `vertices` array that should be drawn to display the currently visible part of the scene displayed in the `XRView`. If this array is empty, the whole region of the `XRView` will be drawn.
- {{domxref("XRVisibilityMaskChangeEvent.session", "session")}} {{ReadOnlyInline}}
- : The {{domxref("XRSession")}} to which the event refers.
- {{domxref("XRVisibilityMaskChangeEvent.vertices", "vertices")}} {{ReadOnlyInline}}
- : An array of coordinates representing the vertices required to draw the entire scene displayed in the `XRView`. If this array is empty, the whole region of the `XRView` will be drawn.

Comment thread
hamishwillee marked this conversation as resolved.
## Examples

### Three.js example

This snippet shows how `visibilitymaskchange` might be used to draw only the visible portion of the `XRView` in a Three.js application. The new view must be drawn using the {{domxref("XRView.projectionMatrix")}} of the relevant `XRView` and a default {{domxref("XRRigidTransform")}}.

```js
session.addEventListener("visibilitymaskchange", onVisibilityMaskChange);

function onVisibilityMaskChange(event) {
const geometry = new BufferGeometry();
geometry.setIndex(new BufferAttribute(event.indices, 1));
const vertices = new Float32Array((event.vertices.length / 2) * 3);
let x = 0,
y = 0;
while (x < event.vertices.length) {
vertices[y++] = event.vertices[x++];
vertices[y++] = event.vertices[x++];
vertices[y++] = -1;
}

geometry.setAttribute("position", new BufferAttribute(vertices, 3));

const mask = event.eye === "left" ? leftEyeMask : rightEyeMask;
const matrix = cameras[event.eye === "left" ? 0 : 1].projectionMatrix;
mask.geometry = geometry;
mask.material = new ShaderMaterial({
vertexShader: _visibility_mask_vertex,
fragmentShader: _visibility_mask_fragment,
uniforms: {
clipMatrix: { value: matrix },
},
});

maskScene = new Scene();
maskScene.add(leftEyeMask);
maskScene.add(rightEyeMask);
}
```

The code snippet is taken from [this fork of WebXRManager.js](https://github.com/cabanier/three.js/blob/78a3227d95fc29e001d8cd139504c643987430c5/src/renderers/webxr/WebXRManager.js).

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}
2 changes: 2 additions & 0 deletions files/en-us/web/api/xrview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The [WebXR Device API](/en-US/docs/Web/API/WebXR_Device_API)'s **`XRView`** inte
- : Which of the two eyes (`left`) or (`right`) for which this `XRView` represents the perspective. This value is used to ensure that any content which is pre-rendered for presenting to a specific eye is distributed or positioned correctly. The value can also be `none` if the `XRView` is presenting monoscopic data (such as a 2D image, a fullscreen view of text, or a close-up view of something that doesn't need to appear in 3D).
- {{domxref("XRView.isFirstPersonObserver", "isFirstPersonObserver")}} {{ReadOnlyInline}} {{Experimental_Inline}}
- : Returns a boolean indicating if the `XRView` is a first-person observer view.
- {{domxref("XRView.index", "index")}} {{ReadOnlyInline}} {{Experimental_Inline}}
- : Returns a number specifying the index of the current `XRView` in the {{domxref("XRViewerPose.views")}} array.
- {{domxref("XRView.projectionMatrix", "projectionMatrix")}} {{ReadOnlyInline}} {{Experimental_Inline}}
- : The projection matrix that will transform the scene to appear correctly given the point-of-view indicated by `eye`. This matrix should be used directly in order to avoid presentation distortions that may lead to potentially serious user discomfort.
- {{domxref("XRView.recommendedViewportScale", "recommendedViewportScale")}} {{ReadOnlyInline}} {{Experimental_Inline}}
Expand Down
36 changes: 36 additions & 0 deletions files/en-us/web/api/xrview/index/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: "XRView: index property"
short-title: index
slug: Web/API/XRView/index
page-type: web-api-instance-property
browser-compat: api.XRView.index
---

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`index`** read-only property of the {{domxref("XRView")}} interface indicates the index of the current `XRView` in the {{domxref("XRViewerPose.views")}} array.

## Value

A number.

## Examples

Comment thread
chrisdavidmills marked this conversation as resolved.
### Basic usage

```js
console.log(xrView.index);
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- {{domxref("XRViewerPose.views")}}
- {{domxref("XRFrame.getViewerPose()")}}
53 changes: 53 additions & 0 deletions files/en-us/web/api/xrvisibilitymaskchangeevent/eye/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: "XRVisibilityMaskChangeEvent: eye property"
short-title: eye
slug: Web/API/XRVisibilityMaskChangeEvent/eye
page-type: web-api-instance-property
browser-compat: api.XRVisibilityMaskChangeEvent.eye
---

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`eye`** read-only property of the {{domxref("XRVisibilityMaskChangeEvent")}} interface indicates the eye the mask applies to.

## Value

An emumerated value indicating which eye the mask applies to from the viewer's perspective.
This can be one of:

- `left`
- : The viewer's left eye.
- `right`
- : The viewer's right eye.
- `none`
- : A monoscopic view, or the view otherwise doesn't represent a particular eye's point-of-view.

## Examples

Comment thread
chrisdavidmills marked this conversation as resolved.
### Basic usage

This example indicates how you might check the `eye` value when the `visibilitymaskchange` event fires and then render a suitable display update depending on the result.

```js
xrSession.addEventListener("visibilitymaskchange", (e) => {
if (e.eye === "left") {
// Render for left eye view
} else if (e.eye === "right") {
// Render for right eye view
} else {
// Render for neutral view
}
});
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- {{domxref("XRView.eye")}}
88 changes: 88 additions & 0 deletions files/en-us/web/api/xrvisibilitymaskchangeevent/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: XRVisibilityMaskChangeEvent
slug: Web/API/XRVisibilityMaskChangeEvent
page-type: web-api-interface
browser-compat: api.XRVisibilityMaskChangeEvent
---

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`XRVisibilityMaskChangeEvent`** of the [WebXR Device API](/en-US/docs/Web/API/WebXR_Device_API) describes the portion of an {{domxref("XRView")}} visible to the user after the view has changed, for example by specifying the eye that the view is relevant to, and the vertices of a visibility mask that defines the visible part of the view. This enables performance improvements by allowing the browser to draw only the visible part of the updated view.

An `XRVisibilityMaskChangeEvent` object is made available as the event object of a {{domxref("XRSession.visibilitymaskchange_event", "visibilitymaskchange")}} event, fired each time the portion of the view displayed to the user changes to provide new information to update the view.

{{InheritanceDiagram}}

## Constructor

- {{domxref("XRVisibilityMaskChangeEvent.XRVisibilityMaskChangeEvent", "XRVisibilityMaskChangeEvent()")}}
- : Creates and returns a new `XRVisibilityMaskChangeEvent` object.

## Instance properties

_In addition to properties inherited from its parent interface, {{domxref("Event")}}, `XRVisibilityMaskChangeEvent` provides the following:_

- {{domxref("XRVisibilityMaskChangeEvent.eye", "eye")}} {{ReadOnlyInline}}
- : The eye the mask applies to.
- {{domxref("XRVisibilityMaskChangeEvent.index", "index")}} {{ReadOnlyInline}}
- : The index of the current {{domxref("XRView")}} in the {{domxref("XRViewerPose.views")}} array.
- {{domxref("XRVisibilityMaskChangeEvent.indices", "indices")}} {{ReadOnlyInline}}
- : An array of values specifying the array positions of the vertices in the [vertices](#vertices) array that define the currently visible part of the scene displayed in the {{domxref("XRView")}}. If this array is empty, the whole region of the `XRView` will be drawn.
- {{domxref("XRVisibilityMaskChangeEvent.session", "session")}} {{ReadOnlyInline}}
- : The {{domxref("XRSession")}} to which the event belongs.
- {{domxref("XRVisibilityMaskChangeEvent.vertices", "vertices")}} {{ReadOnlyInline}}
- : An array of coordinate values representing a visibility mask. If this array is empty, the whole region of the `XRView` will be drawn.

## Instance methods

_While `XRSessionEvent` defines no methods, it inherits methods from its parent interface, {{domxref("Event")}}._

## Examples

### Three.js example

This snippet shows how `visibilitymaskchange` might be used to draw only the visible portion of the `XRView` in a Three.js application. The new view must be drawn using the {{domxref("XRView.projectionMatrix")}} of the relevant `XRView` and a default {{domxref("XRRigidTransform")}}.

```js
session.addEventListener("visibilitymaskchange", onVisibilityMaskChange);

function onVisibilityMaskChange(event) {
const geometry = new BufferGeometry();
geometry.setIndex(new BufferAttribute(event.indices, 1));
const vertices = new Float32Array((event.vertices.length / 2) * 3);
let x = 0,
y = 0;
while (x < event.vertices.length) {
vertices[y++] = event.vertices[x++];
vertices[y++] = event.vertices[x++];
vertices[y++] = -1;
}
Comment on lines +49 to +59
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could probably use some words. IN particular this looks like it is creating a three dimensional structure from the 2D point information in event.vertices - but I am not sure why?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per my other comment you need to iterate through the indices array. Not just increment your own indices.

@toji can help me out here, there MAY be a WebGL or other structure you can basically just pass them into

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is using Three.js, which (as far as I can tell) requires the 'position' attribute of a BufferGeometry to be a packed array of 3D points. So this type of conversion would be necessary.

With raw WebGL there's no specific requirement for the number of elements in an attribute, as the developer interprets it in the shaders. So there are scenarios where you could pass the event.vertices array in directly, just not with Three.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, just realized I probably read Alex's question wrong.

geometry.setIndex(new BufferAttribute(event.indices, 1)); as shown here is fine, because the indices are a Uint32Array and thus are already in the right format.


geometry.setAttribute("position", new BufferAttribute(vertices, 3));

const mask = event.eye === "left" ? leftEyeMask : rightEyeMask;
const matrix = cameras[event.eye === "left" ? 0 : 1].projectionMatrix;
mask.geometry = geometry;
mask.material = new ShaderMaterial({
vertexShader: _visibility_mask_vertex,
fragmentShader: _visibility_mask_fragment,
uniforms: {
clipMatrix: { value: matrix },
},
});

maskScene = new Scene();
maskScene.add(leftEyeMask);
maskScene.add(rightEyeMask);
}
```

The code snippet is taken from [this fork of WebXRManager.js](https://github.com/cabanier/three.js/blob/78a3227d95fc29e001d8cd139504c643987430c5/src/renderers/webxr/WebXRManager.js).

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}
40 changes: 40 additions & 0 deletions files/en-us/web/api/xrvisibilitymaskchangeevent/index/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: "XRVisibilityMaskChangeEvent: index property"
short-title: index
slug: Web/API/XRVisibilityMaskChangeEvent/index
page-type: web-api-instance-property
browser-compat: api.XRVisibilityMaskChangeEvent.index
---

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`index`** read-only property of the {{domxref("XRVisibilityMaskChangeEvent")}} interface indicates the index of the current {{domxref("XRView")}} in the {{domxref("XRViewerPose.views")}} array.

For a stereo view, there will be two views in the array. The `index` property allows you to identify the correct view to re-render, rather than having to re-render all views unnecessarily.

## Value

A number.

## Examples

This example indicates how you might render a display update for a particular {{domxref("XRView")}} by querying the `index` value of the event object when a `visibilitymaskchange` event is fired.

```js
xrSession.addEventListener("visibilitymaskchange", (e) => {
renderNewView(e.index);
});
```

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- {{domxref("XRViewerPose.views")}}
- {{domxref("XRFrame.getViewerPose()")}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: "XRVisibilityMaskChangeEvent: indices property"
short-title: indices
slug: Web/API/XRVisibilityMaskChangeEvent/indices
page-type: web-api-instance-property
browser-compat: api.XRVisibilityMaskChangeEvent.indices
---

{{APIRef("WebXR Device API")}}{{SecureContext_Header}}

The **`indices`** read-only property of the {{domxref("XRVisibilityMaskChangeEvent")}} interface is an array of values specifying the array positions of the vertices in the {{domxref("XRVisibilityMaskChangeEvent.vertices", "vertices")}} array that define the currently visible part of the scene displayed in the {{domxref("XRView")}}. If this array is empty, the whole region of the `XRView` will be drawn.

## Value

A {{domxref("Uint32Array")}}.

## Examples

See the main [`XRVisibilityMaskChangeEvent`](/en-US/docs/Web/API/XRVisibilityMaskChangeEvent) page for an example.

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- {{domxref("XRVisibilityMaskChangeEvent.vertices")}}
Loading
Loading