Start · Sprachen · JavaScript · Referenz · XRDepthInformation

XRDepthInformation

Schnittstelle

Basis-Interface der WebXR-Tiefenerkennung: beschreibt Größe, Koordinatentransformation und Skalierung eines Tiefenpuffers, der die Entfernung zur realen Umgebung angibt.

seit JavaScript Experimentell: Chrome/Edge für Android 90+ (ARCore Kategorie: webapi

Signatur

interface XRDepthInformation

Beschreibung

XRDepthInformation gehört zum WebXR Depth Sensing Module. Das Interface beschreibt einen Tiefenpuffer: ein Raster mit Werten, die für jeden Bildpunkt angeben, wie weit die reale Geometrie (Wände, Böden, Möbel, Hände) vom Gerät entfernt ist. So lassen sich in AR-Anwendungen virtuelle Objekte korrekt hinter realen Gegenständen verdecken (Occlusion), Physik mit der echten Umgebung umsetzen oder Abstände messen.

Instanzen erzeugt man nie selbst. Man bekommt sie über eine der beiden Unterklassen:

  • XRCPUDepthInformation: liefert XRFrame.getDepthInformation(view), wenn die Sitzung "cpu-optimized" nutzt. Die Rohdaten stehen als ArrayBuffer (data) bereit, dazu gibt es die Methode getDepthInMeters(x, y).
  • XRWebGLDepthInformation: liefert XRWebGLBinding.getDepthInformation(view), wenn die Sitzung "gpu-optimized" nutzt. Die Daten liegen dann als WebGL-Textur (texture) vor.

Das Basis-Interface selbst hat diese schreibgeschützten Eigenschaften:

  • width und height (number): Breite und Höhe des Tiefenpuffers in Werten. Sie weichen meist deutlich von der Auflösung der Kamera oder der Ansicht ab (z. B. 160×90).
  • normDepthBufferFromNormView (XRRigidTransform): Transformation von normierten Ansichtskoordinaten (0..1) in normierte Koordinaten des Tiefenpuffers. Man braucht sie, weil der Puffer gegenüber der Ansicht gedreht oder gespiegelt sein kann.
  • rawValueToMeters (number): Faktor, mit dem man einen Rohwert aus dem Puffer multipliziert, um Meter zu erhalten.

Tiefeninformationen sind nur innerhalb des requestAnimationFrame-Callbacks der XR-Sitzung und nur für den aktuellen Frame gültig. Wer außerhalb dieses Frames auf die Daten zugreift, bekommt eine InvalidStateError-Exception.

Rückgabewert

Typ
XRDepthInformation
Beschreibung
Kein Konstruktor. Instanzen (genauer: XRCPUDepthInformation oder XRWebGLDepthInformation) liefern XRFrame.getDepthInformation() bzw. XRWebGLBinding.getDepthInformation(). Beide Methoden geben null zurück, wenn für den Frame keine Tiefendaten vorliegen.

Beispiele

AR-Sitzung mit Tiefenerkennung anfordern

const startAR = async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-ar'))) {
    console.warn('immersive-ar wird nicht unterstützt');
    return null;
  }

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

  // Welche Variante hat der Browser tatsächlich gewählt?
  console.log('Nutzung:', session.depthUsage);
  console.log('Format:', session.depthDataFormat);
  return session;
};

// Muss durch eine Benutzeraktion ausgelöst werden
document.querySelector('#ar-start').addEventListener('click', startAR);
Nutzung: cpu-optimized Format: luminance-alpha

Entfernung in der Bildmitte messen (CPU)

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

const onXRFrame = (time, frame) => {
  session.requestAnimationFrame(onXRFrame);

  const pose = frame.getViewerPose(refSpace);
  if (!pose) return;

  for (const view of pose.views) {
    const depthInfo = frame.getDepthInformation(view); // XRCPUDepthInformation
    if (!depthInfo) continue;

    // Normierte Ansichtskoordinaten (0..1): Bildmitte
    const meters = depthInfo.getDepthInMeters(0.5, 0.5);
    console.log(`Puffer ${depthInfo.width}×${depthInfo.height}, Abstand Mitte: ${meters.toFixed(2)} m`);
  }
};

session.requestAnimationFrame(onXRFrame);
Puffer 160×90, Abstand Mitte: 1.37 m

Rohwerte manuell mit rawValueToMeters umrechnen

// Nur im Frame-Callback gültig; Format "luminance-alpha" = 16-Bit-Ganzzahlen
const readRawDepth = (depthInfo, col, row) => {
  const raw = new Uint16Array(depthInfo.data);
  const index = row * depthInfo.width + col;
  return raw[index] * depthInfo.rawValueToMeters;
};

const onXRFrame = (time, frame) => {
  session.requestAnimationFrame(onXRFrame);
  const pose = frame.getViewerPose(refSpace);
  const view = pose?.views[0];
  const depthInfo = view && frame.getDepthInformation(view);
  if (!depthInfo) return;

  const col = Math.floor(depthInfo.width / 2);
  const row = Math.floor(depthInfo.height / 2);
  console.log('Rohwert-Abstand:', readRawDepth(depthInfo, col, row).toFixed(3), 'm');
};

session.requestAnimationFrame(onXRFrame);
Rohwert-Abstand: 1.372 m

Tiefentextur für Occlusion im Shader (GPU)

const gl = canvas.getContext('webgl2', { xrCompatible: true });
const glBinding = new XRWebGLBinding(session, gl);

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

  for (const view of pose.views) {
    const depthInfo = glBinding.getDepthInformation(view); // XRWebGLDepthInformation
    if (!depthInfo) continue;

    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_2D, depthInfo.texture);
    gl.uniform1i(uDepthTexture, 1);
    gl.uniform1f(uRawValueToMeters, depthInfo.rawValueToMeters);
    // Transformationsmatrix Ansicht -> Tiefenpuffer an den Shader übergeben
    gl.uniformMatrix4fv(uUvTransform, false, depthInfo.normDepthBufferFromNormView.matrix);
    // ... Szene zeichnen, im Fragment-Shader Tiefe vergleichen
  }
};

session.requestAnimationFrame(onXRFrame);