Start · Sprachen · JavaScript · Referenz · XRDepthInformation.normDepthBufferFromNormView

XRDepthInformation.normDepthBufferFromNormView

Eigenschaft

Schreibgeschütztes <code>XRRigidTransform</code>, das normalisierte View-Koordinaten in normalisierte Koordinaten des Tiefenpuffers umrechnet.

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

Signatur

XRDepthInformation.normDepthBufferFromNormView

Beschreibung

Die schreibgeschützte Eigenschaft normDepthBufferFromNormView des Interfaces XRDepthInformation liefert ein XRRigidTransform. Diese Transformation rechnet einen Punkt in normalisierten View-Koordinaten (Ursprung oben links, Wertebereich 0–1 auf beiden Achsen) in normalisierte Koordinaten des Tiefenpuffers um. Der Tiefenpuffer des Geräts ist nämlich nicht zwangsläufig genauso ausgerichtet wie die gerenderte Ansicht: Er kann zum Beispiel wegen der Bildschirmausrichtung gedreht oder gespiegelt sein.

Brauchen wirst du die Eigenschaft immer dann, wenn du selbst auf die Rohdaten des Tiefenpuffers zugreifst. Das betrifft vor allem zwei Fälle:

  • den direkten Zugriff auf XRCPUDepthInformation.data auf der CPU, zum Beispiel für eigene Filter oder eine Kollisionsprüfung, und
  • das Auslesen der Tiefentextur aus XRWebGLDepthInformation.texture in einem Shader, etwa für Verdeckung (Occlusion) oder Physik-Effekte.

Für einzelne Punkte kannst du auf der CPU auch einfach XRCPUDepthInformation.getDepthInMeters(x, y) aufrufen. Diese Methode wendet die Transformation bereits intern an.

Die Matrix erhältst du über normDepthBufferFromNormView.matrix als Float32Array mit 16 Werten in spaltenweiser Anordnung (column-major). Du kannst sie direkt mit gl.uniformMatrix4fv() an WebGL übergeben. Umgekehrt findest du die Rücktransformation unter normDepthBufferFromNormView.inverse.

Rückgabewert

Typ
XRRigidTransform
Beschreibung
Eine starre Transformation (Position und Orientierung). Die Eigenschaft matrix enthält die 4×4-Matrix als Float32Array in spaltenweiser Anordnung.

Beispiele

Session mit Tiefenerkennung starten und die Matrix auslesen

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

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 = frame.getDepthInformation(view);
    if (!depthInfo) continue;
    // 4x4-Matrix, spaltenweise angeordnet
    console.log(depthInfo.normDepthBufferFromNormView.matrix);
  }
};

session.requestAnimationFrame(onFrame);
Float32Array(16) [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1] // Beispiel: um 90° gedrehter Puffer

Rohdaten auf der CPU manuell auslesen

// x, y: normalisierte View-Koordinaten (0..1, Ursprung oben links)
const depthAt = (depthInfo, x, y) => {
  const m = depthInfo.normDepthBufferFromNormView.matrix;
  // Punkt (x, y, 0, 1) mit der spaltenweisen Matrix transformieren
  const u = m[0] * x + m[4] * y + m[12];
  const v = m[1] * x + m[5] * y + m[13];

  const { width, height, rawValueToMeters } = depthInfo;
  const col = Math.min(width - 1, Math.max(0, Math.floor(u * width)));
  const row = Math.min(height - 1, Math.max(0, Math.floor(v * height)));

  // Format 'luminance-alpha' = 16 Bit pro Pixel
  const raw = new Uint16Array(depthInfo.data)[row * width + col];
  return raw * rawValueToMeters;
};

// innerhalb des Animation-Frame-Callbacks:
// const meters = depthAt(depthInfo, 0.5, 0.5);
// Kontrolle: depthInfo.getDepthInMeters(0.5, 0.5) liefert denselben Wert
// console.log(meters.toFixed(2));
1.37

Matrix als Uniform an einen WebGL-Shader übergeben (GPU-Pfad)

// Fragment-Shader (GLSL ES 1.0)
const fragmentSrc = `
  precision mediump float;
  uniform sampler2D uDepthTexture;
  uniform mat4 uUvTransform;
  uniform float uRawValueToMeters;
  varying vec2 vViewUv; // normalisierte View-Koordinaten

  float depthInMeters(vec2 viewUv) {
    vec2 depthUv = (uUvTransform * vec4(viewUv, 0.0, 1.0)).xy;
    vec2 packed = texture2D(uDepthTexture, depthUv).ra; // luminance-alpha
    return dot(packed, vec2(255.0, 256.0 * 255.0)) * uRawValueToMeters;
  }

  void main() {
    float d = depthInMeters(vViewUv);
    gl_FragColor = vec4(vec3(clamp(d / 5.0, 0.0, 1.0)), 1.0);
  }
`;

// im Frame-Callback (Session mit usagePreference: ['gpu-optimized'])
const drawDepth = (gl, glBinding, view, program) => {
  const depthInfo = glBinding.getDepthInformation(view);
  if (!depthInfo) return;

  gl.activeTexture(gl.TEXTURE0);
  gl.bindTexture(gl.TEXTURE_2D, depthInfo.texture);
  gl.uniform1i(gl.getUniformLocation(program, 'uDepthTexture'), 0);
  gl.uniformMatrix4fv(
    gl.getUniformLocation(program, 'uUvTransform'),
    false,
    depthInfo.normDepthBufferFromNormView.matrix
  );
  gl.uniform1f(
    gl.getUniformLocation(program, 'uRawValueToMeters'),
    depthInfo.rawValueToMeters
  );
  // ... Vollbild-Quad zeichnen
};