Start · Sprachen · JavaScript · Referenz · XRVisibilityMaskChangeEvent.indices

XRVisibilityMaskChangeEvent.indices

Eigenschaft

Schreibgeschütztes <code>Uint32Array</code> mit Vertex-Indizes, die je zu dritt ein Dreieck der sichtbaren Fläche einer <code>XRView</code> bilden.

seit JavaScript Experimentell: nur einzelne Chromium-basierte Brow Kategorie: webapi

Signatur

XRVisibilityMaskChangeEvent.indices

Beschreibung

Die schreibgeschützte Eigenschaft indices des Interfaces XRVisibilityMaskChangeEvent enthält ein Uint32Array. Je drei aufeinanderfolgende Werte beschreiben ein Dreieck. Alle Dreiecke zusammen bilden die Sichtbarkeitsmaske: den Bereich einer Ansicht (XRView), den der Nutzer auf dem Display des Headsets tatsächlich sieht.

Wichtig: Ein Index zeigt nicht direkt auf einen einzelnen Eintrag im Array vertices. Er zeigt auf ein Koordinatenpaar. Der Index i steht also für den Punkt (vertices[2 * i], vertices[2 * i + 1]). Die Koordinaten liegen im normalisierten Projektionsraum der jeweiligen Ansicht.

Das Ereignis visibilitymaskchange wird auf der XRSession ausgelöst. Das geschieht beim Start der Sitzung und immer dann, wenn sich die Maske einer Ansicht ändert. Die Maske wird vor allem zur Leistungsoptimierung verwendet: Man zeichnet sie zum Beispiel in den Stencil- oder Tiefenpuffer. So werden Pixel, die durch die Linsen ohnehin nicht zu sehen sind, gar nicht erst berechnet. Ist indices leer, gibt es für diese Ansicht keine Einschränkung und die ganze Fläche ist sichtbar.

Rückgabewert

Typ
Uint32Array
Beschreibung
Ein Array mit Vertex-Indizes. Die Länge ist ein Vielfaches von 3, denn je drei Werte bilden ein Dreieck. Jeder Wert zeigt auf ein Koordinatenpaar in vertices. Ein leeres Array bedeutet: keine Maske, die ganze Fläche ist sichtbar.

Beispiele

Auf Maskenänderungen reagieren

const session = await navigator.xr.requestSession('immersive-vr');

session.addEventListener('visibilitymaskchange', (event) => {
  const { index, indices, vertices } = event;
  console.log(`Ansicht ${index}: ${indices.length / 3} Dreiecke, ${vertices.length / 2} Eckpunkte`);
});
Ansicht 0: 32 Dreiecke, 48 Eckpunkte Ansicht 1: 32 Dreiecke, 48 Eckpunkte

Dreiecke aus indices und vertices auflösen

const getTriangles = ({ indices, vertices }) => {
  const point = (i) => [vertices[2 * i], vertices[2 * i + 1]];
  const triangles = [];
  for (let t = 0; t < indices.length; t += 3) {
    triangles.push([point(indices[t]), point(indices[t + 1]), point(indices[t + 2])]);
  }
  return triangles;
};

session.onvisibilitymaskchange = (event) => {
  const triangles = getTriangles(event);
  console.log('Erstes Dreieck:', triangles[0]);
};
Erstes Dreieck: [[-0.93, -0.41], [-0.87, 0.52], [0, 0]]

Maske als WebGL-Indexpuffer für den Stencil-Pass hochladen

const masks = new Map();

session.addEventListener('visibilitymaskchange', ({ index, vertices, indices }) => {
  const vbo = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  const ibo = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

  masks.set(index, { vbo, ibo, count: indices.length });
});

// Später im Render-Loop je Ansicht:
// gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
// gl.drawElements(gl.TRIANGLES, mask.count, gl.UNSIGNED_INT, 0);

// Wichtig · Fallstricke

  • Indizes zeigen auf Paare: Ein Index zeigt auf ein Koordinatenpaar, nicht auf einen einzelnen Array-Eintrag. In WebGL muss die Stride deshalb 2 Floats betragen (vertexAttribPointer(loc, 2, …)). Wer den Index direkt in vertices nachschlägt, bekommt falsche Punkte.
  • 32-Bit-Indizes: drawElements mit gl.UNSIGNED_INT funktioniert in WebGL 1 nur mit der Erweiterung OES_element_index_uint. In WebGL 2 ist das ohne Erweiterung möglich.
  • Leeres Array: Ist das Array leer, gibt es keine Maske. Diesen Fall abfangen und dann auf den Stencil-Pass verzichten.
  • Kompatibilität: Die Eigenschaft ist experimentell und nur in wenigen Chromium-basierten XR-Browsern verfügbar. Vorher prüfen, z. B. mit 'XRVisibilityMaskChangeEvent' in window. WebXR funktioniert nur in sicheren Kontexten (HTTPS).
  • Das Ereignis kann während einer Sitzung mehrfach kommen. Alte Puffer dann mit gl.deleteBuffer() freigeben.