Signatur
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:
|
Rückgabewert
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);
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']oderoptionalFeatures: ['layers']angefordert werden. Sonst wirft die Methode einenNotSupportedError. - Ist die Sitzung bereits beendet, wird ein
InvalidStateErrorgeworfen. - 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. BeiisStatic: truedarf die Textur nach dem ersten Zeichnen nur nach einemredraw-Ereignis erneut abgefragt werden. - Stereo-Layouts und
\"texture-array\"brauchen einen WebGL-2-Kontext. Große Werte fürviewPixelWidth/viewPixelHeightkosten spürbar Grafikspeicher.