Signatur
Beschreibung
XRProjectionLayer gehört zum WebXR Layers Module und stellt die klassische „Hauptebene“ einer immersiven Sitzung dar: Sie deckt das gesamte Sichtfeld beider Augen ab und wird in jedem Frame neu gerendert. Damit ersetzt sie in Layer-basierten Anwendungen die ältere XRWebGLLayer, bietet aber mehr Kontrolle, z. B. über Textur-Arrays (ein Draw-Aufruf für beide Augen mittels Multiview), Farb- und Tiefenformate sowie die Auflösung über einen Skalierungsfaktor.
Einen Konstruktor gibt es nicht. Instanzen werden über XRWebGLBinding.createProjectionLayer(options) erzeugt und anschließend per XRSession.updateRenderState({ layers: [...] }) in die Sitzung eingehängt. Im Render-Loop liefert XRWebGLBinding.getViewSubImage(layer, view) pro Ansicht ein XRWebGLSubImage mit Farbtextur, Tiefentextur, Viewport und ggf. Array-Index, in das gezeichnet wird.
Wichtige Eigenschaften (zusätzlich zu den geerbten aus XRCompositionLayer wie layout, blendTextureSourceAlpha, mipLevels, needsRedraw und destroy()):
textureWidth,textureHeight(schreibgeschützt): Größe der zugrunde liegenden Texturen in Pixeln.textureArrayLength(schreibgeschützt): Anzahl der Ebenen, wenntextureType: "texture-array"verwendet wird, sonst1.ignoreDepthValues(schreibgeschützt):true, wenn der Compositor den Tiefenpuffer nicht auswertet.fixedFoveation: Zahl von0bis1bzw.null; steuert, wie stark die Auflösung am Bildrand reduziert wird (Foveated Rendering), um Leistung zu sparen.deltaPose(schreibgeschützt, optional): Pose-Differenz für Reprojektion, sofern vom Gerät unterstützt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options.textureType | "texture" | "texture-array" | "texture" | Optionen-Feld von createProjectionLayer(): "texture-array" liefert ein TEXTURE_2D_ARRAY (für Multiview, WebGL2 nötig). |
| $options.colorFormat | GLenum | gl.RGBA8 | Internes Farbformat der Farbtexturen, z. B. gl.RGBA8 oder gl.SRGB8_ALPHA8. |
| $options.depthFormat | GLenum | gl.DEPTH_COMPONENT | Format der Tiefen-/Stenciltextur; 0 bedeutet: keine Tiefentextur anlegen. |
| $options.scaleFactor | number | 1.0 | Skalierung der empfohlenen Texturauflösung; Werte < 1 sparen GPU-Leistung, Werte > 1 erhöhen die Schärfe. |
Beispiele
Projektionsebene erzeugen und in die Sitzung einhängen
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['layers']
});
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const binding = new XRWebGLBinding(session, gl);
const projLayer = binding.createProjectionLayer({
textureType: 'texture',
colorFormat: gl.RGBA8,
depthFormat: gl.DEPTH_COMPONENT24,
scaleFactor: 1.0
});
session.updateRenderState({ layers: [projLayer] });
console.log(`Textur: ${projLayer.textureWidth}x${projLayer.textureHeight}`);
return { session, gl, binding, projLayer };
};
startXR().catch(err => console.error('XR nicht verfügbar:', err));
Render-Loop mit getViewSubImage()
const { session, gl, binding, projLayer } = await startXR();
const refSpace = await session.requestReferenceSpace('local');
const fb = gl.createFramebuffer();
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
for (const view of pose.views) {
const sub = binding.getViewSubImage(projLayer, view);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, sub.colorTexture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D, sub.depthStencilTexture, 0);
const { x, y, width, height } = sub.viewport;
gl.viewport(x, y, width, height);
gl.clearColor(0.1, 0.1, 0.2, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// drawScene(view.projectionMatrix, view.transform.inverse.matrix);
}
};
session.requestAnimationFrame(onFrame);
Foveated Rendering für mehr Leistung aktivieren
const tuneLayer = (layer) => {
if (layer.fixedFoveation !== null) {
layer.fixedFoveation = 0.5; // mittlere Foveation
}
console.log('Foveation:', layer.fixedFoveation,
'| Array-Länge:', layer.textureArrayLength,
'| Tiefe ignoriert:', layer.ignoreDepthValues);
};
tuneLayer(projLayer);