Start · Sprachen · JavaScript · Referenz · new XRWebGLLayer()

new XRWebGLLayer()

Methode

Erzeugt eine <code>XRWebGLLayer</code>, die einen WebGL-Kontext mit einer <code>XRSession</code> verbindet, damit Frames im XR-Gerät dargestellt werden.

seit JavaScript WebXR Device API – Chromium 79+ (Chrome, Edge, Sam Kategorie: webapi

Signatur

new XRWebGLLayer(session, context, layerInit)

Beschreibung

Der Konstruktor XRWebGLLayer() erzeugt eine Ebene (Layer), über die ein WebGL- bzw. WebGL2-Kontext die Bilder für ein XR-Gerät (VR-Brille, AR-fähiges Smartphone) liefert. Die Ebene enthält einen eigenen WebGLFramebuffer (layer.framebuffer). In diesen rendert man pro Frame und pro Auge (XRView). Das Gerät zeigt das Ergebnis dann an.

Man benutzt ihn gleich nach dem Start einer Sitzung mit navigator.xr.requestSession(). Die neue Ebene wird über session.updateRenderState({ baseLayer }) als Basisebene festgelegt. Erst danach ruft die Sitzung Frames über requestAnimationFrame() auf und stellt sie dar.

Wichtig: Der WebGL-Kontext muss XR-kompatibel sein. Dafür erzeugt man ihn entweder mit der Option { xrCompatible: true } oder ruft vorher await gl.makeXRCompatible() auf. Außerdem darf die Sitzung noch nicht beendet sein. Mit dem Wörterbuch layerInit legt man fest, ob Tiefenpuffer, Stencil-Puffer, Alpha-Kanal und Antialiasing verwendet werden und wie hoch die Framebuffer-Auflösung ist.

Parameter

Name Typ Default Beschreibung
$session Pflicht XRSession Die aktive XR-Sitzung, für die die Ebene erzeugt wird. Ist sie schon beendet, wird ein InvalidStateError ausgelöst.
$context Pflicht WebGLRenderingContext | WebGL2RenderingContext Der WebGL-Kontext, der die Bilder rendert. Er muss XR-kompatibel sein (xrCompatible: true oder makeXRCompatible()). Ist das nicht der Fall, wird ein InvalidStateError ausgelöst.
$layerInit XRWebGLLayerInit {} Optionales Konfigurationsobjekt mit diesen Feldern:
  • antialias (boolean, Standard true)
  • depth (boolean, Standard true)
  • stencil (boolean, Standard false)
  • alpha (boolean, Standard true)
  • ignoreDepthValues (boolean, Standard false)
  • framebufferScaleFactor (number, Standard 1.0): Skalierung relativ zur nativen Auflösung

Rückgabewert

Typ
XRWebGLLayer
Beschreibung
Eine neue XRWebGLLayer. Wichtige Eigenschaften sind framebuffer, framebufferWidth und framebufferHeight. Mit der Methode getViewport(view) erhält man den Bildausschnitt für ein bestimmtes Auge.

Beispiele

Immersive VR-Sitzung starten und Basisebene setzen

const startVR = async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.log('WebXR VR wird nicht unterstützt');
    return;
  }

  // Sitzungen müssen durch eine Benutzeraktion (z. B. Klick) gestartet werden
  const session = await navigator.xr.requestSession('immersive-vr');

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

  const layer = new XRWebGLLayer(session, gl);
  session.updateRenderState({ baseLayer: layer });

  console.log(`Framebuffer: ${layer.framebufferWidth}x${layer.framebufferHeight}`);
  return { session, gl };
};

document.querySelector('#vr-button').addEventListener('click', startVR);
Framebuffer: 3664x1920 (je nach Gerät)

Nachträglich XR-kompatibel machen und mit Optionen konfigurieren

const canvas = document.querySelector('#scene');
const gl = canvas.getContext('webgl'); // ohne xrCompatible erzeugt

const enterAR = async () => {
  const session = await navigator.xr.requestSession('immersive-ar');
  await gl.makeXRCompatible();

  const layer = new XRWebGLLayer(session, gl, {
    antialias: false,             // spart Rechenleistung auf Mobilgeräten
    alpha: true,                  // Kamerabild bleibt sichtbar
    framebufferScaleFactor: 0.75  // geringere Auflösung, höhere Bildrate
  });

  session.updateRenderState({ baseLayer: layer });
  console.log('Antialiasing aktiv:', layer.antialias);
};

document.querySelector('#ar-button').addEventListener('click', enterAR);
Antialiasing aktiv: false

Render-Schleife: pro Auge in den Framebuffer der Ebene zeichnen

const run = async (session, gl) => {
  const refSpace = await session.requestReferenceSpace('local');

  const onFrame = (time, frame) => {
    session.requestAnimationFrame(onFrame);
    const layer = session.renderState.baseLayer;
    const pose = frame.getViewerPose(refSpace);
    if (!pose) return;

    gl.bindFramebuffer(gl.FRAMEBUFFER, layer.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 = layer.getViewport(view);
      gl.viewport(vp.x, vp.y, vp.width, vp.height);
      // hier Szene mit view.projectionMatrix und view.transform zeichnen
    }
  };

  session.requestAnimationFrame(onFrame);
};

// Wichtig · Fallstricke

  • XR-Kompatibilität: Ist der Kontext nicht XR-kompatibel, wirft der Konstruktor einen InvalidStateError. Dasselbe gilt, wenn die Sitzung schon beendet ist oder der WebGL-Kontext verloren wurde (isContextLost()).
  • makeXRCompatible() kann den Kontext auf eine andere GPU verlegen. Dabei geht der Kontext verloren, und alle Texturen, Puffer und Shader müssen neu angelegt werden. Deshalb ist xrCompatible: true schon beim Erzeugen des Kontexts meist die bessere Wahl.
  • framebuffer ist bei immersiven Sitzungen ein undurchsichtiges Objekt. Man darf es nicht mit deleteFramebuffer() löschen, und seine Anhänge (Attachments) lassen sich nicht auslesen. Außerhalb eines XR-Frames zu rendern hat keine sichtbare Wirkung.
  • framebufferScaleFactor ist nur ein Wunsch an das Gerät. Die tatsächliche Größe steht in framebufferWidth/framebufferHeight. XRWebGLLayer.getNativeFramebufferScaleFactor(session) liefert den Faktor für die native Auflösung.
  • Kompatibilität: Die WebXR Device API braucht einen sicheren Kontext (HTTPS). Sie wird in Chromium-Browsern und im Meta Quest Browser unterstützt, in Firefox und Safari (Desktop) nicht; Apple Vision Pro unterstützt WebXR teilweise. In iframes ist die Berechtigungsrichtlinie xr-spatial-tracking nötig.
  • Für mehrere Ebenen oder Ebenen mit besserer Leistung gibt es die WebXR Layers API (XRWebGLBinding, XRProjectionLayer). Sie wird jedoch bisher kaum unterstützt.