Signatur
Beschreibung
Die schreibgeschützte Eigenschaft rawValueToMeters der Schnittstelle XRDepthInformation gibt eine Zahl zurück. Mit ihr rechnet man die rohen Werte aus dem Tiefenpuffer der WebXR Depth Sensing API in Meter um: Meter = Rohwert × rawValueToMeters. Das Gerät (z. B. ein ARCore-Smartphone) legt Tiefen oft als 16-Bit-Ganzzahlen ab, etwa in Millimetern. Dann ist der Faktor 0.001.
Man braucht die Eigenschaft immer dann, wenn man den Tiefenpuffer selbst ausliest, statt die Hilfsmethode zu verwenden. Typische Fälle:
- Auf der CPU liest man mehrere Werte am Stück aus
XRCPUDepthInformation.data, zum Beispiel für ein Histogramm, eine Punktwolke oder die Kollisionserkennung. - Auf der GPU wird die Tiefentextur aus
XRWebGLDepthInformation.textureim Shader ausgewertet, etwa für die Verdeckung virtueller Objekte durch reale Gegenstände. Der Faktor wird dann als Uniform an den Shader übergeben.
Für einzelne Punkte auf der CPU ist XRCPUDepthInformation.getDepthInMeters(x, y) bequemer, weil die Methode Skalierung und Koordinatentransformation übernimmt. Sobald man aber viele Werte verarbeitet oder auf der GPU arbeitet, ist die Multiplikation mit rawValueToMeters der vorgesehene Weg.
Rückgabewert
0.001, wenn der Puffer Millimeter enthält. Bei "float32"-Puffern ist der Wert oft 1. Darauf darf man sich aber nicht verlassen.Beispiele
Rohwerte auf der CPU in Meter umrechnen
// Session mit CPU-optimierter Tiefenerkennung anfordern
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['depth-sensing', 'local'],
depthSensing: {
usagePreference: ['cpu-optimized'],
dataFormatPreference: ['luminance-alpha', 'float32']
}
});
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;
// Passenden TypedArray zum ausgehandelten Format wählen
const raw = session.depthDataFormat === 'float32'
? new Float32Array(depth.data)
: new Uint16Array(depth.data);
// Mittleres Pixel des Tiefenpuffers (Pufferkoordinaten)
const cx = Math.floor(depth.width / 2);
const cy = Math.floor(depth.height / 2);
const meters = raw[cy * depth.width + cx] * depth.rawValueToMeters;
console.log(`Faktor: ${depth.rawValueToMeters}, Mitte: ${meters.toFixed(2)} m`);
}
};
session.requestAnimationFrame(onFrame);
Nächstgelegenen Punkt im ganzen Puffer finden
// depth: XRCPUDepthInformation aus frame.getDepthInformation(view)
const findNearest = (depth, isFloat) => {
const raw = isFloat ? new Float32Array(depth.data) : new Uint16Array(depth.data);
let min = Infinity;
for (const value of raw) {
// 0 bedeutet: kein gültiger Messwert
if (value > 0 && value < min) min = value;
}
return min === Infinity ? null : min * depth.rawValueToMeters;
};
const nearest = findNearest(depth, session.depthDataFormat === 'float32');
if (nearest !== null && nearest < 0.5) {
console.warn(`Achtung: Objekt in ${nearest.toFixed(2)} m Entfernung`);
}
Faktor als Uniform an einen WebGL-Shader übergeben
// Session mit 'gpu-optimized' angefordert; gl und program existieren bereits
const glBinding = new XRWebGLBinding(session, gl);
const uRawToMeters = gl.getUniformLocation(program, 'u_rawValueToMeters');
const uDepthTex = gl.getUniformLocation(program, 'u_depthTexture');
const drawView = (view) => {
const depth = glBinding.getDepthInformation(view);
if (!depth) return;
gl.useProgram(program);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, depth.texture);
gl.uniform1i(uDepthTex, 0);
// Im Shader: float meters = rawDepth * u_rawValueToMeters;
gl.uniform1f(uRawToMeters, depth.rawValueToMeters);
// ... Zeichenaufrufe für die Verdeckung
};
// Wichtig · Fallstricke
- Experimentell: Derzeit nur in Chromium-Browsern auf Android mit ARCore-Unterstützung verfügbar. Firefox und Safari unterstützen die Depth Sensing API nicht. Die API funktioniert nur in sicheren Kontexten (HTTPS) und in einer
immersive-ar-Session mit dem Feature"depth-sensing". - Nicht hartkodieren: Der Faktor kann je nach Gerät, Datenformat (
session.depthDataFormat) und Implementierung verschieden sein. Lies ihn deshalb in jedem Frame aus dem aktuellenXRDepthInformation-Objekt. - Passenden TypedArray wählen: Bei
"luminance-alpha"(bzw."unsigned-short") sind die Werte 16-Bit-Ganzzahlen, alsoUint16Array. Bei"float32"ist es einFloat32Array. Mit dem falschen Array-Typ bekommt man trotz korrektem Faktor unsinnige Werte. - Rohwert 0 steht in der Regel für „keine gültige Messung“ und sollte vor der Umrechnung herausgefiltert werden.
- Koordinaten: Die Skalierung übernimmt
rawValueToMeters, die Koordinatentransformation nicht. Um Bildschirm- bzw. View-Koordinaten auf Pufferkoordinaten abzubilden, braucht mannormDepthBufferFromNormView. - Die Daten eines
XRDepthInformation-Objekts gelten nur innerhalb des Animations-Callbacks, in dem sie abgefragt wurden. Außerhalb davon wird beim Zugriff eineInvalidStateError-Ausnahme ausgelöst.