Start · Sprachen · JavaScript · Referenz · XRRenderState

XRRenderState

Schnittstelle

Enthält die aktuell gültigen Render-Einstellungen einer <code>XRSession</code>, z. B. Clipping-Ebenen, Sichtfeld und Ziel-Layer, die bestimmen, wie Frames zusammengesetzt werden.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

interface XRRenderState

Beschreibung

XRRenderState beschreibt, wie der XR-Kompositor die Bilder einer XRSession zusammensetzt. Ein Objekt dieses Typs bekommt man nur lesend über XRSession.renderState. Es gibt keinen öffentlichen Konstruktor. Die Werte sind schreibgeschützt. Ändern kann man sie ausschließlich mit XRSession.updateRenderState(). Dieser Methode übergibt man ein Wörterbuch vom Typ XRRenderStateInit.

Die wichtigsten Eigenschaften:

  • baseLayer (XRWebGLLayer | null): die WebGL-Ebene, in die gerendert wird.
  • layers (XRLayer[]): geordnete Liste von Ebenen, wenn das WebXR Layers Module unterstützt wird. Schließt sich mit baseLayer gegenseitig aus.
  • depthNear / depthFar (number): Abstand der nahen und fernen Clipping-Ebene in Metern. Standardwerte sind 0.1 und 1000.
  • inlineVerticalFieldOfView (number | null): vertikales Sichtfeld in Radiant. Gilt nur für inline-Sitzungen (Standard: π/2), bei immersiven Sitzungen ist der Wert null.
  • passthroughFullyObscured (boolean | undefined, experimentell): gibt an, ob die Durchsicht auf die reale Umgebung (Passthrough) vollständig verdeckt ist.

Änderungen über updateRenderState() werden nicht sofort wirksam. Sie gelten erst ab dem nächsten Animationsframe. Das Objekt, das session.renderState liefert, ist pro Frame eine Momentaufnahme. Man sollte es deshalb in jedem Frame neu abfragen und nicht zwischenspeichern.

Parameter

Name Typ Default Beschreibung
$baseLayer XRWebGLLayer | null null Eigenschaft von XRRenderStateInit für updateRenderState(): die WebGL-Ebene, deren Framebuffer der Kompositor anzeigt.
$layers XRLayer[] | null null Liste der Kompositions-Ebenen (WebXR Layers). Darf nicht zusammen mit baseLayer gesetzt werden.
$depthNear number 0.1 Nahe Clipping-Ebene in Metern. Sie muss kleiner als depthFar sein.
$depthFar number 1000 Ferne Clipping-Ebene in Metern.
$inlineVerticalFieldOfView number Math.PI / 2 Vertikales Sichtfeld in Radiant, nur für inline-Sitzungen. Bei immersiven Sitzungen wirft das Setzen einen InvalidStateError.

Rückgabewert

Typ
XRRenderState
Beschreibung
Wird über XRSession.renderState gelesen. Liefert die aktuell aktiven, schreibgeschützten Render-Einstellungen der Sitzung.

Beispiele

Immersive Sitzung starten und baseLayer setzen

const startXR = async () => {
  if (!(await navigator.xr?.isSessionSupported('immersive-vr'))) {
    console.log('immersive-vr wird nicht unterstützt');
    return;
  }
  const session = await navigator.xr.requestSession('immersive-vr');
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl2', { xrCompatible: true });

  // Render-Zustand konfigurieren (wirkt ab dem nächsten Frame)
  session.updateRenderState({
    baseLayer: new XRWebGLLayer(session, gl),
    depthNear: 0.05,
    depthFar: 500
  });

  const refSpace = await session.requestReferenceSpace('local');
  session.requestAnimationFrame((time, frame) => {
    const { renderState } = session;
    console.log(renderState.depthNear, renderState.depthFar);
  });
};

document.querySelector('#enter-vr').addEventListener('click', startXR);
0.05 500

Render-Zustand in jedem Frame auslesen

const onXRFrame = (time, frame) => {
  const session = frame.session;
  session.requestAnimationFrame(onXRFrame);

  // renderState in jedem Frame neu abfragen, nicht zwischenspeichern
  const layer = session.renderState.baseLayer;
  if (!layer) return;

  gl.bindFramebuffer(gl.FRAMEBUFFER, layer.framebuffer);
  const pose = frame.getViewerPose(refSpace);
  pose?.views.forEach((view) => {
    const vp = layer.getViewport(view);
    gl.viewport(vp.x, vp.y, vp.width, vp.height);
    // ... Szene mit view.projectionMatrix zeichnen
  });
};

Sichtfeld einer inline-Sitzung anpassen

const inlineSession = await navigator.xr.requestSession('inline');
const gl = document.querySelector('canvas').getContext('webgl', { xrCompatible: true });

inlineSession.updateRenderState({
  baseLayer: new XRWebGLLayer(inlineSession, gl),
  inlineVerticalFieldOfView: Math.PI / 3 // 60°
});

inlineSession.requestAnimationFrame(() => {
  const fov = inlineSession.renderState.inlineVerticalFieldOfView;
  console.log(`FOV: ${(fov * 180 / Math.PI).toFixed(0)}°`);
});
FOV: 60°

// Wichtig · Fallstricke

  • Verzögerte Wirkung: updateRenderState() ändert session.renderState erst ab dem nächsten Frame. Liest man direkt nach dem Aufruf, erhält man noch die alten Werte.
  • Nicht zwischenspeichern: Pro Frame kann ein neues XRRenderState-Objekt entstehen. Deshalb session.renderState immer im Frame-Callback abfragen.
  • Bildschirmausgabe: Ohne gesetzten baseLayer bzw. layers zeigt die Sitzung nichts an, und die Callbacks von requestAnimationFrame werden nicht ausgeführt.
  • baseLayer und layers gleichzeitig zu setzen, führt zu einem NotSupportedError. inlineVerticalFieldOfView bei einer immersiven Sitzung zu setzen, führt zu einem InvalidStateError.
  • Der WebGL-Kontext muss mit xrCompatible: true erzeugt oder nachträglich mit gl.makeXRCompatible() kompatibel gemacht werden.
  • Kompatibilität: WebXR steht nur in sicheren Kontexten (HTTPS) zur Verfügung und muss gegebenenfalls über die Permissions Policy xr-spatial-tracking freigegeben werden. Firefox und Safari (Desktop) unterstützen die API nicht. layers und passthroughFullyObscured sind experimentell. Vor der Nutzung immer navigator.xr und isSessionSupported() prüfen.