Start · Sprachen · JavaScript · Referenz · VRDisplay

VRDisplay

Schnittstelle

Steht in der veralteten WebVR API für ein VR-Gerät (Headset) und bietet Zugriff auf Pose, Augenparameter, Darstellung und den gerätespezifischen Render-Loop.

seit JavaScript WebVR 1.1 (veraltet, nie Baseline). Durch die WebX deprecated seit ja Kategorie: webapi

Signatur

interface VRDisplay extends EventTarget

Beschreibung

Ein VRDisplay steht für ein einzelnes VR-Gerät, zum Beispiel ein Headset wie Oculus Rift oder HTC Vive, das die WebVR API unterstützt. Einen Konstruktor gibt es nicht. Instanzen bekommst du nur über navigator.getVRDisplays(), das ein Promise mit einem Array aller verfügbaren Geräte liefert. Außerdem stecken sie in der Eigenschaft display von VRDisplayEvent-Objekten.

Das Interface fasst alles zusammen, was man zum Rendern einer VR-Szene braucht:

  • Eigenschaften: capabilities (VRDisplayCapabilities), displayId, displayName, isPresenting, depthNear/depthFar (Clipping-Ebenen in Metern), stageParameters (Raumgröße für Room-Scale) und das veraltete isConnected.
  • Darstellung: requestPresent(layers) startet die Ausgabe eines <canvas> auf dem Headset, exitPresent() beendet sie, getLayers() liefert die aktiven Ebenen.
  • Render-Loop: requestAnimationFrame(callback) und cancelAnimationFrame(handle) laufen mit der Bildwiederholrate des Headsets (oft 90 Hz), nicht mit der des Monitors. submitFrame() schickt das fertig gerenderte Bild an das Gerät.
  • Tracking-Daten: getFrameData(frameData) füllt ein VRFrameData-Objekt mit Pose sowie View- und Projektionsmatrizen für beide Augen. getEyeParameters("left"|"right") liefert Auflösung und Versatz pro Auge. getPose() und resetPose() sind veraltet.

Ein typischer Ablauf sieht so aus: Gerät ermitteln, bei einer Nutzeraktion requestPresent() aufrufen, die Canvas-Größe nach getEyeParameters() einstellen und dann in vrDisplay.requestAnimationFrame() pro Bild getFrameData() lesen, beide Augen rendern und submitFrame() aufrufen. Für neue Projekte solltest du VRDisplay nicht mehr verwenden. Der Nachfolger ist die WebXR Device API mit XRSession.

Rückgabewert

Typ
VRDisplay
Beschreibung
Wird nicht direkt erzeugt. Instanzen kommen über navigator.getVRDisplays() (Promise<VRDisplay[]>) oder über event.display eines VRDisplayEvent.

Beispiele

Verfügbare VR-Geräte ermitteln

const findVRDisplay = async () => {
  if (!('getVRDisplays' in navigator)) {
    console.log('WebVR wird nicht unterstützt – bitte WebXR verwenden.');
    return null;
  }
  const displays = await navigator.getVRDisplays();
  if (displays.length === 0) {
    console.log('Kein VR-Gerät gefunden.');
    return null;
  }
  const vrDisplay = displays[0];
  console.log(`Gerät: ${vrDisplay.displayName} (ID ${vrDisplay.displayId})`);
  console.log('Kann präsentieren:', vrDisplay.capabilities.canPresent);
  console.log('Positions-Tracking:', vrDisplay.capabilities.hasPosition);
  return vrDisplay;
};

findVRDisplay();
Gerät: Oculus Rift CV1 (ID 1) Kann präsentieren: true Positions-Tracking: true

Präsentation auf Klick starten und Canvas-Größe setzen

const canvas = document.querySelector('#vr-canvas');
const button = document.querySelector('#enter-vr');

const setup = async () => {
  const [vrDisplay] = await navigator.getVRDisplays();
  if (!vrDisplay) return;

  // requestPresent() braucht eine Nutzeraktion
  button.addEventListener('click', async () => {
    try {
      await vrDisplay.requestPresent([{ source: canvas }]);
      const left = vrDisplay.getEyeParameters('left');
      const right = vrDisplay.getEyeParameters('right');
      // Beide Augen liegen nebeneinander auf einem Canvas
      canvas.width = Math.max(left.renderWidth, right.renderWidth) * 2;
      canvas.height = Math.max(left.renderHeight, right.renderHeight);
      console.log('Präsentiert:', vrDisplay.isPresenting);
    } catch (err) {
      console.error('requestPresent fehlgeschlagen:', err);
    }
  });

  window.addEventListener('vrdisplaypresentchange', () => {
    console.log('Präsentationsstatus:', vrDisplay.isPresenting);
  });
};

setup();
Präsentiert: true Präsentationsstatus: true

Render-Loop mit getFrameData() und submitFrame()

const frameData = new VRFrameData();
let frameHandle = null;

// gl ist ein WebGLRenderingContext des präsentierten Canvas
const startLoop = (vrDisplay, gl, drawScene) => {
  const onFrame = () => {
    frameHandle = vrDisplay.requestAnimationFrame(onFrame);
    vrDisplay.getFrameData(frameData);

    const { width, height } = gl.canvas;
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Linkes Auge
    gl.viewport(0, 0, width / 2, height);
    drawScene(frameData.leftProjectionMatrix, frameData.leftViewMatrix);

    // Rechtes Auge
    gl.viewport(width / 2, 0, width / 2, height);
    drawScene(frameData.rightProjectionMatrix, frameData.rightViewMatrix);

    vrDisplay.submitFrame();
  };
  frameHandle = vrDisplay.requestAnimationFrame(onFrame);
};

const stopLoop = async (vrDisplay) => {
  vrDisplay.cancelAnimationFrame(frameHandle);
  await vrDisplay.exitPresent();
  console.log('VR beendet');
};
VR beendet

// Wichtig · Fallstricke

Veraltet und nicht standardisiert: Die WebVR API ist nie über den Entwurfsstatus hinausgekommen und wurde durch die WebXR Device API ersetzt (navigator.xr.requestSession(), XRSession, XRFrame). Chrome hatte WebVR nur hinter einem Flag oder als Origin Trial, und Firefox hat die Unterstützung inzwischen entfernt. Oculus Browser und Samsung Internet haben sie ebenfalls aufgegeben. Für neuen Code solltest du WebXR verwenden oder für Altprojekte das Polyfill webvr-polyfill bzw. webxr-polyfill einsetzen.

  • requestPresent() funktioniert nur innerhalb einer Nutzeraktion (z. B. click). Sonst wird das Promise abgelehnt.
  • Die API steht nur in einem sicheren Kontext (HTTPS) zur Verfügung. In iframes kann eine Permissions Policy sie zusätzlich sperren.
  • Für den VR-Loop musst du vrDisplay.requestAnimationFrame() nutzen, nicht window.requestAnimationFrame(). Das Fenster-Pendant läuft mit der Monitorfrequenz und erzeugt im Headset Ruckeln und Übelkeit.
  • getPose(), resetPose() und isConnected sind schon innerhalb von WebVR veraltet. Nimm stattdessen getFrameData() und die Events vrdisplayconnect/vrdisplaydisconnect.
  • Lege ein VRFrameData-Objekt einmal an und verwende es in jedem Frame wieder. Neue Objekte pro Bild belasten den Garbage Collector.