Start · Sprachen · JavaScript · Referenz · XRWebGLBinding.getDepthInformation()

XRWebGLBinding.getDepthInformation()

Methode

Gibt für eine <code>XRView</code> ein <code>XRWebGLDepthInformation</code>-Objekt zurück, dessen WebGL-Textur die Tiefendaten der realen Umgebung enthält.

seit JavaScript Experimentell: Chrome/Edge 90+ auf Android (ARCore Kategorie: webapi

Signatur

XRWebGLBinding.prototype.getDepthInformation(view)

Beschreibung

Mit getDepthInformation() holen Sie in einer immersiven AR-Sitzung die Tiefenkarte der realen Umgebung als WebGLTexture. Die Methode gehört zum WebXR Depth Sensing Module und wird bei GPU-optimierter Nutzung (usagePreference: "gpu-optimized") verwendet. Die Tiefendaten liegen dann direkt auf der Grafikkarte und können im Shader ausgewertet werden, ohne dass sie erst über die CPU laufen.

Typische Einsatzfälle sind die Verdeckung (Occlusion) virtueller Objekte durch reale Gegenstände, physikalisch plausible Schatten und Kollisionen oder Visualisierungen der Tiefe zum Debuggen. Das zurückgegebene Objekt enthält neben texture auch width, height, rawValueToMeters (Umrechnungsfaktor der Rohwerte in Meter) und normDepthBufferFromNormView (eine XRRigidTransform, mit der normalisierte View-Koordinaten in Texturkoordinaten des Tiefenpuffers umgerechnet werden).

Die Methode darf nur innerhalb eines aktiven requestAnimationFrame-Callbacks aufgerufen werden, und zwar mit einer XRView, die aus frame.getViewerPose() desselben Frames stammt. Die Sitzung muss mit dem Feature "depth-sensing" angefordert worden sein. Für die CPU-Variante gibt es das Gegenstück XRFrame.getDepthInformation().

Parameter

Name Typ Default Beschreibung
$view Pflicht XRView Die Ansicht (meist ein Auge bzw. der Kamerablick), für die Tiefendaten abgefragt werden. Muss aus XRViewerPose.views des aktuellen Frames stammen.

Rückgabewert

Typ
XRWebGLDepthInformation | null
Beschreibung
Ein XRWebGLDepthInformation-Objekt mit texture, width, height, rawValueToMeters und normDepthBufferFromNormView. null, wenn für diesen Frame (noch) keine Tiefendaten vorliegen.

Beispiele

AR-Sitzung mit GPU-Tiefenerkennung anfordern

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });

const session = await navigator.xr.requestSession('immersive-ar', {
  requiredFeatures: ['depth-sensing'],
  depthSensing: {
    usagePreference: ['gpu-optimized'],
    dataFormatPreference: ['luminance-alpha', 'float32']
  }
});

// Tatsächlich gewählte Einstellungen prüfen
console.log(session.depthUsage, session.depthDataFormat);

const binding = new XRWebGLBinding(session, gl);
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
gpu-optimized luminance-alpha

Tiefentextur im Render-Loop abrufen und binden

const refSpace = await session.requestReferenceSpace('local');

const onFrame = (time, frame) => {
  session.requestAnimationFrame(onFrame);
  const pose = frame.getViewerPose(refSpace);
  if (!pose) return;

  for (const view of pose.views) {
    const depthInfo = binding.getDepthInformation(view);
    if (!depthInfo) continue; // noch keine Daten in diesem Frame

    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_2D, depthInfo.texture);
    gl.uniform1i(uDepthTexture, 1);
    gl.uniform1f(uRawValueToMeters, depthInfo.rawValueToMeters);
    gl.uniformMatrix4fv(uUvTransform, false,
      depthInfo.normDepthBufferFromNormView.matrix);

    // ... Szene für diese View zeichnen
  }
};
session.requestAnimationFrame(onFrame);

Fragment-Shader: Verdeckung virtueller Objekte (luminance-alpha)

const occlusionFragmentShader = `#version 300 es
precision highp float;
uniform sampler2D uDepthTexture;
uniform mat4 uUvTransform;
uniform float uRawValueToMeters;
in vec2 vNormViewUv;     // 0..1 im View
in float vVirtualDepth;  // Abstand des virtuellen Fragments in Metern
out vec4 fragColor;

float realDepth(vec2 uv) {
  vec2 depthUv = (uUvTransform * vec4(uv, 0.0, 1.0)).xy;
  // luminance-alpha: zwei 8-Bit-Kanäle ergeben einen 16-Bit-Wert
  vec2 packed = texture(uDepthTexture, depthUv).ra;
  return dot(packed, vec2(255.0, 256.0 * 255.0)) * uRawValueToMeters;
}

void main() {
  if (realDepth(vNormViewUv) < vVirtualDepth) discard; // reales Objekt davor
  fragColor = vec4(0.2, 0.6, 1.0, 1.0);
}`;
console.log('Shader-Länge:', occlusionFragmentShader.length > 0);
Shader-Länge: true

// Wichtig · Fallstricke

  • Experimentell: Die Methode wird derzeit nur von Chromium-Browsern auf Android mit ARCore unterstützt (Chrome 90+). Firefox und Safari unterstützen sie nicht. Prüfen Sie vorab mit 'getDepthInformation' in XRWebGLBinding.prototype, ob sie verfügbar ist.
  • NotSupportedError: Das passiert, wenn "depth-sensing" nicht aktiviert wurde oder session.depthUsage nicht "gpu-optimized" ist. Bei "cpu-optimized" verwenden Sie stattdessen XRFrame.getDepthInformation().
  • InvalidStateError: Das passiert, wenn der Frame nicht aktiv ist, der Aufruf außerhalb eines Animations-Callbacks erfolgt oder die XRView aus einem anderen Frame stammt.
  • Die Textur gibt es nur für den aktuellen Frame. Speichern Sie sie nicht und verwenden Sie sie nicht in späteren Frames weiter. Die Textur ist schreibgeschützt.
  • Das Datenformat (session.depthDataFormat) bestimmt, wie der Shader die Werte dekodieren muss: "luminance-alpha" bzw. "unsigned-short" liefern 16-Bit-Werte, "float32" liefert Gleitkommazahlen. Die Rohwerte werden immer mit rawValueToMeters multipliziert.
  • Die Auflösung der Tiefenkarte ist meist deutlich niedriger als die Kameraauflösung. Rechnen Sie Texturkoordinaten immer über normDepthBufferFromNormView um.