Signatur
Beschreibung
Die schreibgeschützte Eigenschaft depthStencilTexture eines XRWebGLSubImage-Objekts liefert die WebGLTexture, die der XR-Compositor für Tiefen- (und ggf. Stencil-)Informationen einer Ebene bereitstellt. Das Sub-Image selbst erhältst du pro Frame über XRWebGLBinding.getViewSubImage() (Projektionsebenen, eine pro Ansicht/Auge) oder XRWebGLBinding.getSubImage() (Quad-, Zylinder-, Equirect- und Cube-Ebenen).
Du hängst diese Textur an einen eigenen WebGLFramebuffer an – typischerweise als gl.DEPTH_ATTACHMENT oder, bei einem kombinierten Format wie DEPTH24_STENCIL8, als gl.DEPTH_STENCIL_ATTACHMENT. Zusammen mit colorTexture ergibt das ein vollständiges Render-Ziel. Stellt die Anwendung dem Compositor Tiefenwerte bereit, kann das Laufzeitsystem die Reprojektion verbessern und Ebenen korrekt miteinander verdecken lassen.
Der Wert ist null, wenn die Ebene ohne Tiefenformat erzeugt wurde, also beim Erstellen depthFormat weggelassen oder 0 übergeben wurde. Wurde die Ebene mit textureType: "texture-array" angelegt, ist die Textur ein TEXTURE_2D_ARRAY. In diesem Fall wählst du die richtige Schicht über imageIndex und hängst sie mit gl.framebufferTextureLayer() an.
Rückgabewert
null, wenn die Ebene ohne depthFormat erzeugt wurde.Beispiele
Tiefentextur einer Projektionsebene an den Framebuffer hängen
// Setup (einmalig, innerhalb einer immersiven Session mit Feature "layers")
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const glBinding = new XRWebGLBinding(session, gl);
const layer = glBinding.createProjectionLayer({
textureType: 'texture',
depthFormat: gl.DEPTH_COMPONENT24
});
session.updateRenderState({ layers: [layer] });
const fb = gl.createFramebuffer();
const onXRFrame = (time, frame) => {
session.requestAnimationFrame(onXRFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
for (const view of pose.views) {
const subImage = glBinding.getViewSubImage(layer, view);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, subImage.colorTexture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D, subImage.depthStencilTexture, 0);
const { x, y, width, height } = subImage.viewport;
gl.viewport(x, y, width, height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
drawScene(view); // eigene Renderfunktion
}
};
session.requestAnimationFrame(onXRFrame);
Auf null prüfen und eine eigene Renderbuffer-Tiefe als Fallback nutzen
const attachDepth = (gl, subImage, fallback) => {
if (subImage.depthStencilTexture) {
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D, subImage.depthStencilTexture, 0);
return 'compositor-depth';
}
// Ebene ohne depthFormat erzeugt -> eigenen Tiefenpuffer verwenden
gl.bindRenderbuffer(gl.RENDERBUFFER, fallback);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24,
subImage.textureWidth, subImage.textureHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER, fallback);
return 'eigener-renderbuffer';
};
const quad = glBinding.createQuadLayer({ space: refSpace, viewPixelWidth: 1024, viewPixelHeight: 768 });
const sub = glBinding.getSubImage(quad, frame);
console.log(attachDepth(gl, sub, gl.createRenderbuffer()));
Texture-Array-Ebene mit kombiniertem Depth/Stencil-Format
const layer = glBinding.createProjectionLayer({
textureType: 'texture-array',
depthFormat: gl.DEPTH24_STENCIL8
});
// im Frame-Callback, pro Ansicht:
const subImage = glBinding.getViewSubImage(layer, view);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
subImage.colorTexture, 0, subImage.imageIndex);
gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,
subImage.depthStencilTexture, 0, subImage.imageIndex);
console.log(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE);