Start · Sprachen · JavaScript · Referenz · XRWebGLBinding.createQuadLayer()

XRWebGLBinding.createQuadLayer()

Methode

Erzeugt ein <code>XRQuadLayer</code>, also eine flache, rechteckige Kompositionsebene, die frei im 3D-Raum einer WebXR-Sitzung platziert wird.

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

Signatur

XRWebGLBinding.prototype.createQuadLayer(options)

Beschreibung

createQuadLayer() gehört zur WebXR Layers API und erzeugt über ein XRWebGLBinding eine Quad-Ebene: ein flaches Rechteck mit fester Breite und Höhe (in Metern), das an einer Position im Raum „schwebt“. Der Inhalt wird per WebGL in eine eigene Textur gerendert und vom XR-Compositor direkt dargestellt, nicht über die normale Projektionsebene.

Quad-Ebenen eignen sich vor allem für Text, Menüs, Bedienoberflächen und Videos. Der Compositor tastet die Textur mit der vollen Auflösung des Displays ab. Dadurch wirkt der Inhalt deutlich schärfer als bei einem texturierten Rechteck in der 3D-Szene, das zweimal umgerechnet wird (erst in die Projektionsebene, dann auf das Display).

Damit die Ebene sichtbar wird, musst du sie in das Array layers von XRSession.updateRenderState() aufnehmen. Gezeichnet wird in jedem Frame über XRWebGLBinding.getSubImage(layer, frame). Die Methode liefert die Farbtextur und den Viewport, die du an einen Framebuffer anhängst. Nach dem Erzeugen kannst du Position und Größe über die Eigenschaften transform, width und height des XRQuadLayer ändern.

Parameter

Name Typ Default Beschreibung
$options Pflicht Object Konfigurationsobjekt mit folgenden Eigenschaften:
  • space (XRSpace, Pflicht): Referenzraum, in dem die Ebene verankert ist.
  • viewPixelWidth / viewPixelHeight (number, Pflicht): Auflösung der Textur in Pixeln.
  • width / height (number, Standard 1.0): Größe der Ebene in Metern.
  • transform (XRRigidTransform): Position und Ausrichtung relativ zu space.
  • layout ("default"|"mono"|"stereo"|"stereo-left-right"|"stereo-top-bottom", Standard "mono"): Aufteilung der Bilder für linkes und rechtes Auge.
  • textureType ("texture"|"texture-array", Standard "texture"): Art der WebGL-Textur. "texture-array" setzt WebGL 2 voraus.
  • colorFormat (GLenum, Standard gl.RGBA): Farbformat der Textur.
  • depthFormat (GLenum): optionales Tiefenformat, z. B. gl.DEPTH_COMPONENT.
  • mipLevels (number, Standard 1): Anzahl der Mipmap-Stufen.
  • isStatic (boolean, Standard false): true bedeutet, dass der Inhalt nur bei Bedarf neu gezeichnet wird (nach dem Ereignis redraw). Das spart Speicher und Rechenzeit.
  • clearOnAccess (boolean, Standard true): Textur bei jedem Zugriff über getSubImage() leeren.

Rückgabewert

Typ
XRQuadLayer
Beschreibung
Ein neues XRQuadLayer-Objekt. Sichtbar wird es erst, wenn du es an session.updateRenderState({ layers }) übergibst.

Beispiele

Sitzung mit Layers-Feature starten und Quad-Ebene anlegen

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);

// Panel 2 m vor dem Nutzer, auf Augenhöhe
const quadLayer = binding.createQuadLayer({
  space: refSpace,
  viewPixelWidth: 1024,
  viewPixelHeight: 512,
  width: 1.0,
  height: 0.5,
  layout: 'mono',
  transform: new XRRigidTransform({ x: 0, y: 1.5, z: -2 })
});

const projLayer = binding.createProjectionLayer();
// Reihenfolge = Zeichenreihenfolge: Quad liegt über der Szene
session.updateRenderState({ layers: [projLayer, quadLayer] });
console.log(quadLayer.width, quadLayer.height);
1 0.5

In die Quad-Ebene rendern (pro Frame)

const fb = gl.createFramebuffer();

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

  const subImage = binding.getSubImage(quadLayer, frame);
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  gl.framebufferTexture2D(
    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    gl.TEXTURE_2D, subImage.colorTexture, 0
  );
  const { x, y, width, height } = subImage.viewport;
  gl.viewport(x, y, width, height);

  // Beispiel: Panel einfarbig blau füllen
  gl.clearColor(0.1, 0.3, 0.8, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
};

session.requestAnimationFrame(onFrame);

Statische UI-Ebene nur bei Bedarf neu zeichnen

const menuLayer = binding.createQuadLayer({
  space: refSpace,
  viewPixelWidth: 800,
  viewPixelHeight: 600,
  width: 0.8,
  height: 0.6,
  isStatic: true,
  transform: new XRRigidTransform({ x: -1, y: 1.4, z: -1.5 })
});

let needsRedraw = true;
// Der Compositor meldet, wenn der Inhalt verloren ging
menuLayer.addEventListener('redraw', () => { needsRedraw = true; });

const drawMenu = (frame) => {
  if (!needsRedraw) return;
  const sub = binding.getSubImage(menuLayer, frame);
  // ... Menü einmalig in sub.colorTexture zeichnen ...
  needsRedraw = false;
};

// Wichtig · Fallstricke

Kompatibilität: Die WebXR Layers API ist experimentell. Unterstützt wird sie vor allem im Meta Quest Browser (Oculus Browser) sowie hinter Flags in Chromium. Firefox und Safari unterstützen sie nicht. Das WebXR Layers Polyfill kann helfen. Nur in sicheren Kontexten (HTTPS) verfügbar.

  • Die Sitzung muss mit requiredFeatures: ['layers'] oder optionalFeatures: ['layers'] angefordert werden. Sonst wirft die Methode einen NotSupportedError.
  • Ist die Sitzung bereits beendet, wird ein InvalidStateError geworfen.
  • Ohne den Eintrag in updateRenderState({ layers }) bleibt die Ebene unsichtbar. Die Reihenfolge im Array bestimmt, welche Ebene über welcher liegt.
  • Rufe getSubImage() nur innerhalb eines XR-Frames auf. Bei isStatic: true darf die Textur nach dem ersten Zeichnen nur nach einem redraw-Ereignis erneut abgefragt werden.
  • Stereo-Layouts und \"texture-array\" brauchen einen WebGL-2-Kontext. Große Werte für viewPixelWidth/viewPixelHeight kosten spürbar Grafikspeicher.