XRView
======

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

**Experimental:** **This is an experimental technology**  
Check the Browser compatibility table carefully before using this in production.

The WebXR Device API's **`XRView`** interface describes a single view into the XR scene for a specific frame, providing orientation and position information for the viewpoint. You can think of it as a description of a specific eye or camera and how it views the world. A 3D frame will involve two views, one for each eye, separated by an appropriate distance which approximates the distance between the viewer's eyes. This allows the two views, when projected in isolation into the appropriate eyes, to simulate a 3D world.

Instance properties
-------------------

`eye` Read only  
Experimental

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).

`isFirstPersonObserver` Read only  
Experimental

Returns a boolean indicating if the `XRView` is a first-person observer view.

`projectionMatrix` Read only  
Experimental

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.

`recommendedViewportScale` Read only  
Experimental

The recommended viewport scale value that you can use for `requestViewportScale()` if the user agent has such a recommendation; `null` otherwise.

`transform` Read only  
Experimental

An `XRRigidTransform` which describes the current position and orientation of the viewpoint in relation to the `XRReferenceSpace` specified when `getViewerPose()` was called on the `XRFrame` being rendered.

Instance methods
----------------

`requestViewportScale()` Read only  
Experimental

Requests that the user agent should set the requested viewport scale for this viewport to the requested value.

Usage notes
-----------

### Positions and number of XRViews per frame

While rendering a scene, the set of views that are used to render the scene for the viewer as of the current frame are obtained by calling the `XRFrame` object's `getViewerPose()` method to get the `XRViewerPose` representing (in essence) the position of the viewer's head. That object's `views` property is a list of all of the `XRView` objects representing the viewpoints which can be used to construct the scene for presentation to the user.

It's possible to have `XRView` objects which represent overlapping regions as well as entirely disparate regions; in a game, you might have views that can be presented to observe a remote site using a security camera or other device, for example. In other words, don't assume there are exactly two views on a given viewer; there can be as few as one (such as when rendering the scene in `inline` mode, and potentially many (especially if the field of view is very large). There might also be views representing observers watching the action, or other viewpoints not directly associated with a player's eye.

In addition, the number of views can change at any time, depending on the needs of the time. So you should process the view list every time without making assumptions based on previous frames.

All positions and orientations within the views for a given `XRViewerPose` are specified in the reference space that was passed to `XRFrame.getViewerPose()`; this is called the **viewer reference space**. The `transform` property describes the position and orientation of the eye or camera represented by the `XRView`, given in that reference space.

### The destination rendering layer

To render a frame, you iterate over the `XRViewerPose`'s views, rendering each of them into the appropriate viewport within the frame's `XRWebGLLayer`. Currently, the specification (and therefore all current implementations of WebXR) is designed around rendering every `XRView` into a single `XRWebGLLayer`, which is then presented on the XR device with half used for the left eye and half for the right eye. The `XRViewport` for each view is used to position the rendering into the correct half of the layer.

If in the future it becomes possible for each view to render into a different layer, there would have to be changes made to the API, so it's safe for now to assume that all views will render into the same layer.

Examples
--------

### Preparing to render every view for a pose

To draw everything the user sees, each frame requires iterating over the list of views returned by the `XRViewerPose` object's `views` list:


```js
for (const view of pose.views) {
  const viewport = glLayer.getViewport(view);

  gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

  // Draw the scene; the eye being drawn is identified
  // by view.eye.
}
```

### Special view transforms

There are a few special transforms that are used on the view while rendering and lighting a scene.

#### Model view matrix

The **model view matrix** is a matrix which defines the position of an object relative to the space in which it's located: If `objectMatrix` is a transform applied to the object to provide its basic position and rotation, then the model view matrix can be computed by multiplying the object's matrix by the inverse of the view transform matrix, like this:


```js
mat4.multiply(modelViewMatrix, view.transform.inverse.matrix, objectMatrix);
```


#### Normal matrix

The model view's **normal matrix** is used when lighting the scene, in order to transform each surface's normal vectors to ensure that the light is reflected in the correct direction given the orientation and position of the surface relative to the light source or sources. It's computed by inverting then transposing the model view matrix:


```js
mat4.invert(normalMatrix, modelViewMatrix);
mat4.transpose(normalMatrix, normalMatrix);
```

### Teleporting an object

To programmatically move and/or rotate (often referred to as **teleporting**) an object, you need to create a new reference space for that object which applies a transform that encapsulates the desired changes. The `createTeleportTransform()` function returns the transform needed to move and rotate an object whose current situation is described by the reference space `refSpace` to a new position and orientation which is computed using previously recorded mouse and keyboard input data which has generated offsets for yaw, pitch, and position along all three axes.


```js
function applyMouseMovement(refSpace) {
  if (
    !mouseYaw &&
    !mousePitch &&
    !axialDistance &&
    !transverseDistance &&
    !verticalDistance
  ) {
    return refSpace;
  }

  // Compute the quaternion used to rotate the image based
  // on the pitch and yaw.

  quat.identity(inverseOrientation);
  quat.rotateX(inverseOrientation, inverseOrientation, -mousePitch);
  quat.rotateY(inverseOrientation, inverseOrientation, -mouseYaw);

  // Compute the true "up" vector for our object.

  vec3.cross(vecX, vecY, cubeOrientation);
  vec3.cross(vecY, cubeOrientation, vecX);

  // Now compute the transform that teleports the object to the
  // specified point and save a copy of it to display to the user
  // later; otherwise we probably wouldn't need to save mouseMatrix
  // at all.

  let newTransform = new XRRigidTransform(
    { x: transverseDistance, y: verticalDistance, z: axialDistance },
    {
      x: inverseOrientation[0],
      y: inverseOrientation[1],
      z: inverseOrientation[2],
      w: inverseOrientation[3],
    },
  );
  mat4.copy(mouseMatrix, newTransform.matrix);

  // Create a new reference space that transforms the object to the new
  // position and orientation, returning the new reference space.

  return refSpace.getOffsetReferenceSpace(newTransform);
}
```


This code is broken into four sections. In the first, the quaternion `inverseOrientation` is computed. This represents the rotation of the object given the values of `mousePitch` (rotation around the object's reference's space's X axis) and `mouseYaw` (rotation around the object's Y axis).

The second section computes the "up" vector for the object. This vector indicates the direction which is "up" in the scene overall, but in the object's reference space.

The third section creates the new `XRRigidTransform`, specifying a point providing the offsets along the three axes as the first parameter, and the orientation quaternion as the second parameter. The returned object's `matrix` property is the actual matrix that transforms points from the scene's reference space to the object's new position.

Finally, a new reference space is created to describe the relationship between the two reference spaces fully. That reference space is returned to the caller.

To use this function, we pass the returned reference space into `XRFrame.getPose()` or `getViewerPose()`, as appropriate for your needs. The returned `XRPose` will then be used to render the scene for the current frame.

You can find a more extensive and complete example in our article Movement, orientation, and motion.

Specifications
--------------

| Specification |
| --- |
| WebXR Device API # xrview-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.