Start · Sprachen · JavaScript · Referenz · XRRenderState.baseLayer

XRRenderState.baseLayer

Eigenschaft

Schreibgeschützte Eigenschaft, die die <code>XRWebGLLayer</code> liefert, in die der Browser die Bilder einer XR-Sitzung rendert und die er dann auf dem Gerät anzeigt.

seit JavaScript WebXR Device API – Chrome/Edge 79+, Samsung Intern Kategorie: webapi

Signatur

XRRenderState.baseLayer

Beschreibung

Die Eigenschaft baseLayer eines XRRenderState-Objekts verweist auf die Basisebene einer WebXR-Sitzung. Das ist in der Regel eine XRWebGLLayer. Sie hängt an einem WebGL-Kontext und stellt einen Framebuffer bereit, in den die Anwendung jedes Bild zeichnet. Der XR-Compositor nimmt diesen Framebuffer und zeigt ihn im Headset oder auf dem AR-Display an.

Gesetzt wird die Ebene nicht direkt über die Eigenschaft, denn sie ist schreibgeschützt. Stattdessen ruft man XRSession.updateRenderState({ baseLayer }) auf. Die Änderung gilt erst ab dem nächsten Animationsbild. Den aktuellen Zustand liest man über session.renderState.baseLayer, zum Beispiel im Callback von requestAnimationFrame(). Dort holt man sich den framebuffer und mit getViewport(view) den Viewport für jedes Auge.

Solange noch keine Ebene gesetzt ist, ist der Wert null. In diesem Fall zeigt die Sitzung nichts an, und requestAnimationFrame-Callbacks werden nicht ausgeführt. Wer das neuere WebXR Layers API nutzt, setzt statt baseLayer die Eigenschaft layers. Beide Varianten lassen sich nicht gleichzeitig verwenden.

Rückgabewert

Typ
XRWebGLLayer | null
Beschreibung
Die aktuell gesetzte Basisebene der Sitzung oder null, wenn noch keine Ebene festgelegt wurde (oder stattdessen layers verwendet wird).

Beispiele

Basisebene beim Start einer VR-Sitzung setzen

const startXR = async () => {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl2', { xrCompatible: true });

  const session = await navigator.xr.requestSession('immersive-vr');
  const layer = new XRWebGLLayer(session, gl);

  // Direkt nach dem Aufruf noch null – die Änderung gilt erst ab dem nächsten Bild
  await session.updateRenderState({ baseLayer: layer });
  console.log(session.renderState.baseLayer === null);

  session.requestAnimationFrame(() => {
    console.log(session.renderState.baseLayer === layer);
  });
};

document.querySelector('#vr-button').addEventListener('click', startXR);
true true

Framebuffer und Viewports im Render-Loop nutzen

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

  const pose = frame.getViewerPose(refSpace);
  if (!pose) return;

  const glLayer = session.renderState.baseLayer;
  gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
  gl.clearColor(0.1, 0.1, 0.2, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  for (const view of pose.views) {
    const vp = glLayer.getViewport(view);
    gl.viewport(vp.x, vp.y, vp.width, vp.height);
    drawScene(view.projectionMatrix, view.transform.inverse.matrix);
  }
};

Ebene mit geringerer Auflösung austauschen (Performance)

const reduceResolution = async (session, gl) => {
  const old = session.renderState.baseLayer;
  const scale = XRWebGLLayer.getNativeFramebufferScaleFactor(session) * 0.5;
  const layer = new XRWebGLLayer(session, gl, { framebufferScaleFactor: scale });
  await session.updateRenderState({ baseLayer: layer });
  console.log(`Alt: ${old.framebufferWidth}px, neu ab nächstem Bild: ${layer.framebufferWidth}px`);
};
Alt: 2880px, neu ab nächstem Bild: 1440px

// Wichtig · Fallstricke

  • Schreibgeschützt: Eine direkte Zuweisung wie renderState.baseLayer = layer hat keine Wirkung. Setze die Ebene immer über session.updateRenderState().
  • Verzögerte Übernahme: Neue Werte werden erst zu Beginn des nächsten Animationsbilds sichtbar. Unmittelbar nach updateRenderState() liefert die Eigenschaft noch den alten Wert.
  • Der WebGL-Kontext muss XR-kompatibel sein: Entweder mit { xrCompatible: true } erzeugen oder vorher await gl.makeXRCompatible() aufrufen. Sonst wirft der XRWebGLLayer-Konstruktor einen InvalidStateError.
  • Die Ebene gehört fest zu ihrer Sitzung. Eine XRWebGLLayer aus einer anderen Sitzung führt zu einem Fehler. Ist die Sitzung beendet, darf man die Ebene nicht weiterverwenden.
  • Wird layers (WebXR Layers API) gesetzt, bleibt baseLayer auf null. Beide gleichzeitig anzugeben löst einen NotSupportedError aus.
  • Kompatibilität: Die Eigenschaft ist nur in sicheren Kontexten (HTTPS) verfügbar. Unterstützt wird sie vor allem von Chromium-Browsern und Headset-Browsern. Firefox und Safari (Desktop) unterstützen WebXR nicht. Prüfe deshalb vorher mit 'xr' in navigator und navigator.xr.isSessionSupported().