Signatur
Beschreibung
Die Eigenschaft needsRedraw gehört zu XRCompositionLayer, der Basisschnittstelle aller Ebenen der WebXR Layers API. Dazu zählen XRProjectionLayer, XRQuadLayer, XRCylinderLayer, XREquirectLayer und XRCubeLayer. Den Wert setzt der Browser. Ist er true, hat der Compositor den Inhalt der Ebene verworfen oder noch nie erhalten. Die Anwendung muss die Ebene dann neu befüllen.
Wichtig ist das vor allem bei statischen Ebenen, also Ebenen mit isStatic: true. Deren Inhalt zeichnet man einmal, danach zeigt der Compositor ihn ohne erneutes Rendern an. Das spart Rechenzeit, zum Beispiel bei Menüs, Texttafeln oder Skyboxen. In bestimmten Fällen kann der Inhalt aber verloren gehen, etwa nach dem Wechsel der Sitzungssichtbarkeit oder wenn der Compositor Speicher freigibt. Dann steht needsRedraw auf true.
Frisch erzeugte Ebenen haben zunächst needsRedraw === true. Normalerweise prüft man den Wert in jedem Durchlauf der Frame-Schleife (XRSession.requestAnimationFrame()). Ist er true, holt man über XRWebGLBinding.getSubImage() die Zieltextur und zeichnet den Inhalt neu. Ist er false, überspringt man die Ebene.
Rückgabewert
true, wenn der Inhalt der Ebene im nächsten Frame neu gezeichnet werden muss. Sonst false.Beispiele
Statische Quad-Ebene nur bei Bedarf neu zeichnen
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 xrGlBinding = new XRWebGLBinding(session, gl);
// Statische Texttafel: Inhalt wird nur bei Bedarf gezeichnet
const quadLayer = xrGlBinding.createQuadLayer({
space: refSpace,
viewPixelWidth: 1024,
viewPixelHeight: 512,
layout: 'mono',
isStatic: true,
transform: new XRRigidTransform({ x: 0, y: 1.5, z: -2 })
});
session.updateRenderState({ layers: [quadLayer] });
const fb = gl.createFramebuffer();
const drawPanel = (frame) => {
const subImage = xrGlBinding.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);
gl.clearColor(0.1, 0.2, 0.4, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// ... hier Text/Grafik der Tafel zeichnen ...
console.log('Tafel neu gezeichnet');
};
const onXRFrame = (time, frame) => {
frame.session.requestAnimationFrame(onXRFrame);
if (quadLayer.needsRedraw) {
drawPanel(frame);
}
};
session.requestAnimationFrame(onXRFrame);
Mehrere Ebenen gemeinsam prüfen
// layers: Array aus XRCompositionLayer-Objekten, renderers: Map Ebene -> Zeichenfunktion
const redrawDirtyLayers = (frame, layers, renderers, binding) => {
let count = 0;
for (const layer of layers) {
if (!layer.needsRedraw) continue;
const subImage = binding.getSubImage(layer, frame);
renderers.get(layer)(subImage);
count++;
}
return count;
};
// In der Frame-Schleife:
// const n = redrawDirtyLayers(frame, [menuLayer, skyLayer], renderers, xrGlBinding);
// if (n > 0) console.log(`${n} Ebene(n) neu gezeichnet`);
Status einer neu erzeugten Ebene abfragen
const cylinderLayer = xrGlBinding.createCylinderLayer({
space: refSpace,
viewPixelWidth: 1200,
viewPixelHeight: 600,
isStatic: true
});
console.log(cylinderLayer.isStatic); // true
console.log(cylinderLayer.needsRedraw); // true – noch kein Inhalt vorhanden
// Wichtig · Fallstricke
- Schreibgeschützt: Eine Zuweisung wie
layer.needsRedraw = falsehat keine Wirkung. Der Browser setzt den Wert selbst zurück, sobald die Anwendung neuen Inhalt geliefert hat. - Statische Ebenen: Laut Spezifikation wirft
XRWebGLBinding.getSubImage()bei einer Ebene mitisStatic: trueeinenInvalidStateError, wennneedsRedrawgeradefalseist. Prüfe den Wert deshalb immer vor dem Zeichnen. - Bei nicht statischen Ebenen, etwa einer
XRProjectionLayermit bewegter Szene, zeichnet man ohnehin in jedem Frame neu. Dort dientneedsRedrawhöchstens als zusätzlicher Hinweis. - Ebenen, die über
XRMediaBindingaus einem<video>erzeugt werden, befüllt der Browser selbst. Für sie spielt die Eigenschaft praktisch keine Rolle. - Kompatibilität: Die WebXR Layers API ist experimentell. Sie läuft nur in sicheren Kontexten (HTTPS) und nur, wenn die Sitzung mit dem Merkmal
'layers'angefordert wurde. Unterstützt wird sie vor allem vom Meta Quest Browser und von Chromium-Browsern mit WebXR. Firefox und Safari unterstützen sie derzeit nicht. Die Verfügbarkeit lässt sich zum Beispiel mit'XRWebGLBinding' in windowundtypeof XRWebGLBinding.prototype.createQuadLayer === 'function'prüfen.