Signatur
Beschreibung
Die schreibgeschützte Eigenschaft data eines XRCPUDepthInformation-Objekts enthält den Tiefenpuffer des aktuellen Frames als ArrayBuffer. Das Objekt bekommt man in einer AR-Sitzung mit dem Feature "depth-sensing" und der Nutzungsart "cpu-optimized" über XRFrame.getDepthInformation(view).
Wie der Puffer aufgebaut ist, hängt von XRSession.depthDataFormat ab:
"luminance-alpha"bzw."unsigned-short": 2 Byte pro Pixel. Man liest ihn am besten über einUint16Arrayaus."float32": 4 Byte pro Pixel. Man liest ihn über einFloat32Arrayaus.
Die Pixel liegen zeilenweise hintereinander (Index = x + y * width). Die Maße stehen in width und height. Die Rohwerte sind noch keine Meter. Man multipliziert sie mit rawValueToMeters, um die Entfernung in Metern zu erhalten. Wenn man nur einzelne Punkte braucht, ist getDepthInMeters(x, y) einfacher. Diese Methode rechnet mit normierten Bildkoordinaten und berücksichtigt normDepthBufferFromNormView gleich mit.
Direkten Zugriff auf data braucht man, wenn man viele Pixel auf einmal verarbeiten will, zum Beispiel für eine Verdeckung (Occlusion) per Software, für Kollisionsprüfungen, zum Erzeugen eines Punkte-Netzes oder um eine Tiefenkarte als Bild darzustellen.
Rückgabewert
width * height * Bytes pro Pixel (2 Byte bei "luminance-alpha"/"unsigned-short", 4 Byte bei "float32").Beispiele
Sitzung mit CPU-Tiefendaten starten
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['depth-sensing', 'local'],
depthSensing: {
usagePreference: ['cpu-optimized'],
dataFormatPreference: ['luminance-alpha', 'float32']
}
});
console.log('Nutzung:', session.depthUsage);
console.log('Format:', session.depthDataFormat);
Puffer je nach Format als typisiertes Array auslesen
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 depth = frame.getDepthInformation(view);
if (!depth) continue;
// Passende Sicht auf den ArrayBuffer wählen
const values = session.depthDataFormat === 'float32'
? new Float32Array(depth.data)
: new Uint16Array(depth.data);
// Pixel in der Bildmitte in Meter umrechnen
const cx = Math.floor(depth.width / 2);
const cy = Math.floor(depth.height / 2);
const raw = values[cx + cy * depth.width];
console.log(`Mitte: ${(raw * depth.rawValueToMeters).toFixed(2)} m`);
}
};
session.requestAnimationFrame(onFrame);
Nächsten Punkt im Tiefenbild finden (z. B. für Kollisionswarnung)
const findNearest = (depth, format) => {
const values = format === 'float32'
? new Float32Array(depth.data)
: new Uint16Array(depth.data);
let min = Infinity;
let minIndex = -1;
for (let i = 0; i < values.length; i++) {
const v = values[i];
if (v > 0 && v < min) { // 0 = kein gültiger Messwert
min = v;
minIndex = i;
}
}
return {
meters: min * depth.rawValueToMeters,
x: minIndex % depth.width,
y: Math.floor(minIndex / depth.width)
};
};
// Innerhalb des Frame-Callbacks aufrufen:
// const nearest = findNearest(frame.getDepthInformation(view), session.depthDataFormat);
// if (nearest.meters < 0.5) console.warn('Hindernis sehr nah!', nearest);
// Wichtig · Fallstricke
- Nur im aktiven Frame gültig: Die Daten dürfen nur im
requestAnimationFrame-Callback des zugehörigenXRFramegelesen werden. Danach löst ein Zugriff einenInvalidStateErroraus. Wer die Werte später noch braucht, kopiert sie vorher, z. B. mitdepth.data.slice(0). - Format beachten: Ob die Werte als
Uint16Arrayoder alsFloat32Arraygelesen werden müssen, hängt immer vonsession.depthDataFormatab. Mit der falschen Sicht auf den Puffer bekommt man unsinnige Werte, aber keine Fehlermeldung. - Rohwerte sind keine Meter: Man muss immer mit
rawValueToMetersmultiplizieren. Der Wert0bedeutet meist, dass es an dieser Stelle keine gültige Messung gibt. - Koordinatensysteme: Das Tiefenbild ist nicht unbedingt genauso ausgerichtet wie die Ansicht, und seine Auflösung ist meist deutlich niedriger. Für Punkte in Bildschirmkoordinaten sollte man
normDepthBufferFromNormViewverwenden oder gleichgetDepthInMeters(). - Bei
"gpu-optimized"gibt es dieses Objekt nicht. Dann liefertXRWebGLBinding.getDepthInformation()eine Textur. - Kompatibilität: Die Eigenschaft ist experimentell und funktioniert derzeit nur in Chromium-Browsern auf Android-Geräten mit ARCore-Tiefenunterstützung. Sie setzt einen sicheren Kontext (HTTPS) voraus.
- Leistung: Wer jeden Frame über alle Pixel läuft, belastet den Hauptthread. Besser ist es, nur einen Teil der Pixel auszuwerten (Unterabtastung) oder die Arbeit in einen Worker auszulagern (vorher kopieren).