Start · Sprachen · JavaScript · Referenz · XRCPUDepthInformation

XRCPUDepthInformation

Schnittstelle

Liefert CPU-zugängliche Tiefendaten einer WebXR-Ansicht, die <code>XRFrame.getDepthInformation()</code> in einer Sitzung mit <code>"cpu-optimized"</code>-Tiefenerkennung zurückgibt.

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

Signatur

interface XRCPUDepthInformation extends XRDepthInformation

Beschreibung

XRCPUDepthInformation gehört zum WebXR Depth Sensing Module. Das Interface stellt den Tiefenpuffer einer einzelnen XRView als ArrayBuffer bereit, den dein JavaScript-Code direkt auslesen kann. Damit misst du, wie weit reale Oberflächen von der Kamera entfernt sind. Das brauchst du etwa für Verdeckung (Occlusion), Physik, Kollisionen oder Abstandsmessungen in AR-Anwendungen.

Du bekommst eine Instanz über XRFrame.getDepthInformation(view). Das funktioniert nur, wenn die Sitzung mit dem Feature "depth-sensing" angefordert wurde und der Browser session.depthUsage === "cpu-optimized" gewählt hat. Bei "gpu-optimized" verwendest du stattdessen XRWebGLBinding.getDepthInformation(), das eine XRWebGLDepthInformation mit Textur zurückgibt.

Diese Mitglieder sind wichtig:

  • data (ArrayBuffer, nur lesbar): die Rohdaten des Tiefenpuffers. Je nach session.depthDataFormat liest du sie als Uint16Array ("luminance-alpha" bzw. "unsigned-short") oder als Float32Array ("float32").
  • getDepthInMeters(x, y): gibt die Tiefe in Metern an einer normalisierten Ansichtskoordinate zurück.
  • Von XRDepthInformation geerbt: width, height, rawValueToMeters (Umrechnungsfaktor für Rohwerte) und normDepthBufferFromNormView (XRRigidTransform von normalisierten Ansichts- in Tiefenpuffer-Koordinaten).

Für einzelne Messpunkte, etwa in der Bildschirmmitte, reicht getDepthInMeters(). Wenn du viele Pixel verarbeitest, zum Beispiel für eine Punktwolke oder ein Gitter, liest du data besser direkt über ein Typed Array. Das ist deutlich schneller.

Rückgabewert

Typ
number
Beschreibung
getDepthInMeters(x, y) gibt den Abstand in Metern von der Ansichtsebene zur realen Oberfläche am angegebenen Punkt zurück. Liegen x oder y außerhalb von [0, 1], wirft die Methode einen RangeError.

Beispiele

AR-Sitzung mit CPU-Tiefenerkennung anfordern

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

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

  // Die tatsächlich gewählte Konfiguration prüfen
  console.log('Nutzung:', session.depthUsage);
  console.log('Format:', session.depthDataFormat);
  return session;
};

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

Abstand in der Bildmitte messen

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

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

  for (const view of pose.views) {
    const depthInfo = frame.getDepthInformation(view);
    if (!depthInfo) continue; // noch keine Tiefendaten verfügbar

    const meters = depthInfo.getDepthInMeters(0.5, 0.5);
    document.querySelector('#distance').textContent =
      `Abstand: ${meters.toFixed(2)} m`;
  }
};

session.requestAnimationFrame(onXRFrame);
Abstand: 1.37 m

Rohdaten direkt auslesen (schnell für viele Pixel)

const readDepthBuffer = (depthInfo, format) => {
  const { width, height, rawValueToMeters, data } = depthInfo;
  const values = format === 'float32'
    ? new Float32Array(data)
    : new Uint16Array(data); // luminance-alpha / unsigned-short

  let nearest = Infinity;
  for (let row = 0; row < height; row++) {
    for (let col = 0; col < width; col++) {
      const raw = values[row * width + col];
      if (raw === 0) continue; // 0 = keine gültige Messung
      nearest = Math.min(nearest, raw * rawValueToMeters);
    }
  }
  return { width, height, nearest };
};

// Innerhalb des XR-Frame-Callbacks aufrufen:
// const depthInfo = frame.getDepthInformation(view);
// console.log(readDepthBuffer(depthInfo, session.depthDataFormat));
{ width: 160, height: 90, nearest: 0.42 }

// Wichtig · Fallstricke

  • Nur im aktiven Frame gültig: Du kannst auf data und getDepthInMeters() nur innerhalb des requestAnimationFrame-Callbacks zugreifen, zu dem der XRFrame gehört. Danach wirft der Zugriff einen InvalidStateError. Wenn du die Daten später brauchst, kopiere sie vorher, zum Beispiel mit data.slice(0).
  • Nutzungsart prüfen: Hat der Browser "gpu-optimized" gewählt, wirft XRFrame.getDepthInformation() einen NotSupportedError. Prüfe deshalb immer session.depthUsage.
  • Koordinatensysteme: getDepthInMeters() erwartet normalisierte Ansichtskoordinaten. Die Indizes in data beziehen sich dagegen auf den Tiefenpuffer. Um zwischen beiden umzurechnen, nutzt du normDepthBufferFromNormView.matrix, besonders wenn das Gerät gedreht ist.
  • Auflösung: Der Tiefenpuffer hat meist eine viel geringere Auflösung als das Kamerabild, oft etwa 160×90. Er kann außerdem Lücken enthalten (Rohwert 0).
  • Kompatibilität: Das Interface ist experimentell und derzeit praktisch nur in Chromium-Browsern auf ARCore-fähigen Android-Geräten verfügbar. Es setzt einen sicheren Kontext (HTTPS) voraus, und das Feature "depth-sensing" muss in requiredFeatures oder optionalFeatures angefordert werden.
  • Datenschutz: Tiefendaten verraten viel über die Umgebung des Nutzers. Der Browser kann dafür eine gesonderte Einwilligung verlangen.