Start · Sprachen · JavaScript · Referenz · XRCompositionLayer

XRCompositionLayer

Schnittstelle

Abstrakte Basisschnittstelle der WebXR Layers API mit gemeinsamen Eigenschaften (z. B. <code>layout</code>, <code>needsRedraw</code>) und der Methode <code>destroy()</code> für alle Kompositions-Layer.

seit JavaScript Experimentell: WebXR Layers API (u. a. Meta Quest Kategorie: webapi

Signatur

interface XRCompositionLayer extends XRLayer

Beschreibung

XRCompositionLayer ist die gemeinsame Basis aller Layer, die der XR-Kompositor direkt darstellt: XRProjectionLayer, XRQuadLayer, XRCylinderLayer, XREquirectLayer und XRCubeLayer. Die Schnittstelle erbt von XRLayer und damit von EventTarget. Du kannst sie nicht selbst instanziieren. Konkrete Layer erzeugst du über Fabrikmethoden von XRWebGLBinding (z. B. createQuadLayer()) oder von XRMediaBinding (Video-Layer).

Kompositions-Layer lohnen sich, wenn Inhalte wie Text, Benutzeroberflächen oder Videos schärfer und stromsparender dargestellt werden sollen. Der Kompositor projiziert sie direkt, ohne dass sie vorher in den Projektions-Framebuffer gezeichnet und dabei erneut abgetastet werden. Das Ergebnis ist bessere Bildqualität bei geringerer GPU-Last.

Gemeinsame Mitglieder:

  • layout (nur lesbar): Aufbau des Layers, z. B. "mono", "stereo", "stereo-left-right", "stereo-top-bottom" oder "default".
  • blendTextureSourceAlpha: Legt fest, ob der Alphakanal der Textur beim Überblenden berücksichtigt wird.
  • forceMonoPresentation: Wenn gesetzt, wird ein Stereo-Layer für beide Augen mono dargestellt.
  • opacity: Deckkraft des Layers, von 0.0 bis 1.0.
  • mipLevels (nur lesbar): Anzahl der tatsächlich angelegten Mip-Stufen.
  • needsRedraw (nur lesbar): true, wenn der Layer neu gezeichnet werden muss, etwa weil der Kompositor den Inhalt verworfen hat.
  • destroy(): Gibt die Ressourcen des Layers frei, insbesondere seine Farb- und Tiefentexturen.

Damit du Layer nutzen kannst, forderst du die Sitzung mit dem Feature "layers" an. Die Layer übergibst du anschließend über session.updateRenderState({ layers: [...] }). Die Reihenfolge im Array bestimmt die Stapelreihenfolge: Das erste Element liegt hinten.

Rückgabewert

Typ
XRCompositionLayer
Beschreibung
Wird nicht direkt erzeugt. Instanzen sind immer konkrete Unterklassen wie XRQuadLayer oder XRProjectionLayer.

Beispiele

Quad-Layer erzeugen und in den Render-State einhängen

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

const session = await navigator.xr.requestSession('immersive-vr', {
  requiredFeatures: ['layers']
});
const refSpace = await session.requestReferenceSpace('local');
const binding = new XRWebGLBinding(session, gl);

// Projektions-Layer für die 3D-Szene
const projLayer = binding.createProjectionLayer({ textureType: 'texture' });

// Quad-Layer für ein scharfes UI-Panel (XRQuadLayer erbt von XRCompositionLayer)
const uiLayer = binding.createQuadLayer({
  space: refSpace,
  viewPixelWidth: 1024,
  viewPixelHeight: 512,
  layout: 'mono',
  transform: new XRRigidTransform({ x: 0, y: 1.5, z: -2 }),
  width: 1.0,
  height: 0.5
});

console.log(uiLayer instanceof XRCompositionLayer, uiLayer.layout);

// Das erste Element im Array liegt hinten
session.updateRenderState({ layers: [projLayer, uiLayer] });
true "mono"

needsRedraw im Frame-Loop auswerten

// Statischen Inhalt nur zeichnen, wenn der Kompositor es verlangt
const drawUi = (gl, binding, layer, frame) => {
  const sub = binding.getSubImage(layer, frame);
  const fb = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    gl.TEXTURE_2D, sub.colorTexture, 0);
  const { x, y, width, height } = sub.viewport;
  gl.viewport(x, y, width, height);
  gl.clearColor(0.1, 0.1, 0.3, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.deleteFramebuffer(fb);
};

const onFrame = (time, frame) => {
  frame.session.requestAnimationFrame(onFrame);
  if (uiLayer.needsRedraw) {
    drawUi(gl, binding, uiLayer, frame);
  }
};
session.requestAnimationFrame(onFrame);

Deckkraft, Alpha-Blending und Aufräumen

// Panel halbtransparent einblenden
uiLayer.blendTextureSourceAlpha = true;
uiLayer.opacity = 0.8;
console.log(`Mip-Stufen: ${uiLayer.mipLevels}`);

// Panel schließen: aus dem Render-State nehmen, dann freigeben
const closePanel = () => {
  session.updateRenderState({ layers: [projLayer] });
  uiLayer.destroy();
};

session.addEventListener('end', () => {
  projLayer.destroy();
});
Mip-Stufen: 1

// Wichtig · Fallstricke

  • Kompatibilität: Die WebXR Layers API ist experimentell. Sie läuft vor allem im Meta Quest Browser und in einigen Chromium-Builds. Firefox und Safari unterstützen sie nicht. Prüfe die Verfügbarkeit mit 'XRWebGLBinding' in window und fordere "layers" nach Möglichkeit als optionalFeatures an, damit du auf XRWebGLLayer zurückfallen kannst.
  • Kein Konstruktor: new XRCompositionLayer() wirft einen TypeError. Layer entstehen nur über XRWebGLBinding bzw. XRMediaBinding.
  • needsRedraw: Wenn der Wert true ist, musst du den Layer im selben Frame neu zeichnen. Sonst zeigt der Kompositor womöglich leeren oder veralteten Inhalt. Das kann jederzeit passieren, z. B. nach einem Wechsel der Sichtbarkeit.
  • destroy(): Nach dem Aufruf sind die Texturen ungültig. Nimm den Layer vorher aus renderState.layers. Ein zerstörter Layer im Render-State führt zu Fehlern.
  • Grenzen: Geräte begrenzen die Anzahl gleichzeitiger Layer. Die Größe von mipLevels kann vom Gerät reduziert werden. Verlasse dich deshalb nicht auf den angeforderten Wert.
  • layers und baseLayer schließen sich im Render-State gegenseitig aus.