Signatur
Beschreibung
Die schreibgeschützte Eigenschaft colorTextureHeight der Schnittstelle XRWebGLSubImage gibt an, wie hoch die WebGL-Textur in colorTexture in Pixeln ist. Ein XRWebGLSubImage erhält man pro Frame über XRWebGLBinding.getSubImage() (z. B. bei Quad-, Zylinder- oder Equirect-Ebenen) oder über XRWebGLBinding.getViewSubImage() (bei Projektionsebenen).
Wichtig ist der Unterschied zum viewport: Der Viewport beschreibt nur den Bereich, in den für eine bestimmte Ansicht gezeichnet wird. Die Textur selbst kann größer sein – etwa wenn beide Augen in einer gemeinsamen, nebeneinander angeordneten Textur liegen oder der Browser mehr Speicher reserviert, als die Ebene braucht. colorTextureHeight (zusammen mit colorTextureWidth) gibt die tatsächliche Größe der Textur an.
Typische Einsatzfälle sind:
- das Anlegen eigener Renderbuffer oder Tiefentexturen in passender Größe, wenn die Ebene ohne Tiefen-/Stencil-Anhang erzeugt wurde,
- das Umrechnen von Viewport-Pixeln in normalisierte Texturkoordinaten (z. B. für Post-Processing-Shader),
- das Prüfen, ob sich die Texturgröße zwischen Frames geändert hat, damit eigene Ressourcen neu angelegt werden können.
Rückgabewert
unsigned long) mit der Höhe der Farbtextur in Pixeln.Beispiele
Texturgröße einer Projektionsebene pro Ansicht auslesen
// Voraussetzung: Session mit requiredFeatures: ['layers']
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const binding = new XRWebGLBinding(session, gl);
const layer = binding.createProjectionLayer({ textureType: 'texture' });
session.updateRenderState({ layers: [layer] });
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
for (const view of pose.views) {
const subImage = binding.getViewSubImage(layer, view);
const { width, height } = subImage.viewport;
console.log(`${view.eye}: Textur ${subImage.colorTextureWidth}x${subImage.colorTextureHeight}, Viewport ${width}x${height}`);
}
};
session.requestAnimationFrame(onFrame);
Passenden Tiefen-Renderbuffer anlegen und bei Größenänderung erneuern
let depthRb = null;
let rbWidth = 0;
let rbHeight = 0;
const ensureDepthBuffer = (gl, subImage) => {
const w = subImage.colorTextureWidth;
const h = subImage.colorTextureHeight;
if (depthRb && w === rbWidth && h === rbHeight) return depthRb;
if (depthRb) gl.deleteRenderbuffer(depthRb);
depthRb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24, w, h);
rbWidth = w;
rbHeight = h;
console.log(`Tiefenpuffer neu: ${w}x${h}`);
return depthRb;
};
// Im Frame-Callback:
// const subImage = binding.getSubImage(quadLayer, frame);
// gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
// gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, subImage.colorTexture, 0);
// gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, ensureDepthBuffer(gl, subImage));
Viewport in normalisierte Texturkoordinaten umrechnen
const viewportToUv = (subImage) => {
const { x, y, width, height } = subImage.viewport;
const texW = subImage.colorTextureWidth;
const texH = subImage.colorTextureHeight;
return {
u0: x / texW,
v0: y / texH,
u1: (x + width) / texW,
v1: (y + height) / texH
};
};
// z. B. als Uniform an einen Post-Processing-Shader übergeben
// const uv = viewportToUv(subImage);
// gl.uniform4f(uvRectLoc, uv.u0, uv.v0, uv.u1, uv.v1);
// Wichtig · Fallstricke
- Nicht mit dem Viewport verwechseln: Für
gl.viewport()immersubImage.viewportverwenden.colorTextureHeightist die Höhe der gesamten Textur und kann größer sein als der Zeichenbereich einer Ansicht. - Nur innerhalb des Frames gültig: Sub-Images und ihre Texturen gelten nur im aktuellen
requestAnimationFrame-Callback. Sub-Image jeden Frame neu holen und Texturen nicht über Frames hinweg speichern. - Texturarrays: Bei Ebenen mit
textureType: 'texture-array'beschreibt der Wert die Höhe einer einzelnen Schicht. Welche Schicht gemeint ist, steht inimageIndex. - Kompatibilität: Die WebXR Layers API ist experimentell und wird bisher vor allem von Chromium-basierten XR-Browsern (z. B. Meta Quest Browser) unterstützt. Die Session muss mit dem Feature
'layers'angefragt werden, und es wird ein sicherer Kontext (HTTPS) benötigt. Vorher prüfen, ob die Funktion vorhanden ist, z. B. mit'XRWebGLBinding' in window. - Es gibt passende Eigenschaften für andere Anhänge:
depthStencilTextureHeightundmotionVectorTextureHeight. Diese können von der Farbtextur abweichen odernullsein.