# WebXR Device API

The WebXR Device API provides access to input and output capabilities commonly associated with Virtual Reality (VR) and Augmented Reality (AR) hardware. It allows you to create immersive 3D experiences directly in the browser.

## 1. The Concept

WebXR replaces the older WebVR API. It is designed to handle both VR (replacing the user's view entirely) and AR (overlaying digital content onto the real world).

*   **VR (Virtual Reality):** Opaque headsets (Oculus, Vive).
*   **AR (Augmented Reality):** Transparent headsets (HoloLens) or phone cameras (mobile AR).

## 2. Checking Support

You access the API via `navigator.xr`. You should check if a specific mode is supported before offering it to the user.

```javascript
if (navigator.xr) {
  navigator.xr.isSessionSupported('immersive-vr')
    .then((isSupported) => {
      if (isSupported) {
        console.log('VR is supported!');
        // Enable VR button
      }
    });
}
```

Modes: `'inline'`, `'immersive-vr'`, `'immersive-ar'`.

## 3. Requesting a Session

To start an experience, you request a session. This usually requires a user gesture.

```javascript
let xrSession = null;

async function onEnterVR() {
  if (!xrSession) {
    xrSession = await navigator.xr.requestSession('immersive-vr', {
      requiredFeatures: ['local-floor']
    });
    
    // Set up the session
    xrSession.addEventListener('end', onSessionEnded);
    
    // Create a WebGL context and set it as the base layer
    const canvas = document.createElement('canvas');
    const gl = canvas.getContext('webgl', { xrCompatible: true });
    
    xrSession.updateRenderState({
      baseLayer: new XRWebGLLayer(xrSession, gl)
    });
    
    // Start the render loop
    xrSession.requestAnimationFrame(onXRFrame);
  }
}
```

## 4. The Render Loop

Unlike standard web apps which use `window.requestAnimationFrame`, WebXR apps use `session.requestAnimationFrame`. The callback receives a timestamp and an `XRFrame` object.

```javascript
function onXRFrame(time, frame) {
  const session = frame.session;
  
  // Queue the next frame
  session.requestAnimationFrame(onXRFrame);
  
  // Get the pose (position and orientation) of the viewer
  const referenceSpace = /* ... obtained earlier ... */;
  const pose = frame.getViewerPose(referenceSpace);
  
  if (pose) {
    const glLayer = session.renderState.baseLayer;
    
    // Bind the framebuffer
    gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
    
    // Clear the canvas
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Loop through views (eyes)
    for (const view of pose.views) {
      const viewport = glLayer.getViewport(view);
      gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
      
      // Draw your 3D scene here using view.projectionMatrix and view.transform
      // drawScene(view);
    }
  }
}
```

## 5. Reference Spaces

Reference spaces define the coordinate system for the tracking.
*   `local`: For seated experiences. Origin is where the user's head was when the session started.
*   `local-floor`: For standing experiences. Origin is on the floor.
*   `viewer`: Origin tracks the viewer's head (useful for inline or HUDs).
*   `unbounded`: For large areas (walking around a room).

```javascript
// Inside the session setup
const referenceSpace = await xrSession.requestReferenceSpace('local-floor');
```

[[programming/javascript/vanilla/javascript]]
[[programming/javascript/vanilla/canvas-api]]
[[programming/javascript/vanilla/promises-async-await]]