Start · Sprachen · JavaScript · Referenz · XRWebGLSubImage.depthStencilTexture

XRWebGLSubImage.depthStencilTexture

Eigenschaft

Schreibgeschützte Eigenschaft mit der Tiefen-/Stencil-<code>WebGLTexture</code>, in die für eine <code>XRCompositionLayer</code> gerendert wird – oder <code>null</code>, falls keine existiert.

seit JavaScript Experimentell (WebXR Layers API) – Chromium-basier Kategorie: webapi

Signatur

XRWebGLSubImage.depthStencilTexture

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

Typ
WebGLTexture | null
Beschreibung
Die vom Compositor verwaltete Tiefen-/Stencil-Textur für den aktuellen Frame oder 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()));
eigener-renderbuffer

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);
true