Start · Sprachen · JavaScript · Referenz · XRVisibilityMaskChangeEvent.vertices

XRVisibilityMaskChangeEvent.vertices

Eigenschaft

Schreibgeschütztes <code>Float32Array</code> mit den Koordinaten der Eckpunkte, aus denen die Sichtbarkeitsmaske einer <code>XRView</code> besteht.

seit JavaScript Experimentell: WebXR (bisher nur in Chromium-Brows Kategorie: webapi

Signatur

XRVisibilityMaskChangeEvent.vertices

Beschreibung

Die schreibgeschützte Eigenschaft vertices des Interfaces XRVisibilityMaskChangeEvent enthält die Eckpunkt-Koordinaten der Sichtbarkeitsmaske einer Ansicht. Die Maske beschreibt den Bereich eines Views (z. B. eines Auges), den der Nutzer durch die Linsen des Headsets tatsächlich sehen kann. Das Event wird als visibilitymaskchange auf der XRSession ausgelöst, sobald sich die Maske ändert oder erstmals verfügbar ist.

Die Werte liegen als flaches Array von Koordinatenpaaren vor (x0, y0, x1, y1, …). Sie werden nicht einzeln ausgewertet, sondern immer zusammen mit indices: Je drei Indizes aus indices verweisen auf drei Eckpunkte in vertices und bilden zusammen ein Dreieck. Alle Dreiecke zusammen ergeben die sichtbare Fläche.

Gedacht ist das vor allem für die Performance-Optimierung: Mit den Daten füllt man vor dem eigentlichen Rendern den Stencil- oder Tiefenpuffer. Dadurch muss der Fragment-Shader keine Pixel berechnen, die ohnehin außerhalb des Sichtfelds der Linse liegen. Zu welchem View die Maske gehört, geben die Eigenschaften eye und index des Events an.

Rückgabewert

Typ
Float32Array
Beschreibung
Ein Array mit den Koordinatenpaaren (x, y) aller Eckpunkte der Sichtbarkeitsmaske. Es kann leer sein, wenn das Gerät keine Einschränkung meldet.

Beispiele

Maskendaten beim Event auslesen

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

session.addEventListener('visibilitymaskchange', (event) => {
  const { eye, index, vertices, indices } = event;
  const vertexCount = vertices.length / 2; // Paare aus x und y
  const triangleCount = indices.length / 3;
  console.log(`View ${index} (${eye}): ${vertexCount} Eckpunkte, ${triangleCount} Dreiecke`);
});
View 0 (left): 64 Eckpunkte, 62 Dreiecke View 1 (right): 64 Eckpunkte, 62 Dreiecke

Maske pro View in WebGL-Puffer hochladen

const gl = canvas.getContext('webgl2', { xrCompatible: true, stencil: true });
const masks = new Map(); // View-Index → Puffer

session.addEventListener('visibilitymaskchange', ({ index, vertices, indices }) => {
  if (vertices.length === 0) {
    masks.delete(index); // keine Maske → ganzen View rendern
    return;
  }
  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 });
});

Eckpunkte in Punktobjekte umwandeln

const toPoints = (vertices) => {
  const points = [];
  for (let i = 0; i < vertices.length; i += 2) {
    points.push({ x: vertices[i], y: vertices[i + 1] });
  }
  return points;
};

session.addEventListener('visibilitymaskchange', (e) => {
  const points = toPoints(e.vertices);
  console.log(points.slice(0, 2));
});
[{ x: -0.93, y: 0.41 }, { x: -0.88, y: 0.57 }]

// Wichtig · Fallstricke

  • Experimentell: Das Feature ist nicht standardisiert und wird bisher nur von einigen Chromium-Browsern auf passender XR-Hardware unterstützt. Vor der Nutzung sollte man prüfen, ob es verfügbar ist, z. B. mit 'XRVisibilityMaskChangeEvent' in window. Ohne Unterstützung wird das Event einfach nie ausgelöst.
  • vertices ist ohne indices nicht verwendbar: Die Eckpunkte stehen nicht in der Reihenfolge der Dreiecke. Deshalb immer indiziert zeichnen, z. B. mit gl.drawElements(gl.TRIANGLES, …, gl.UNSIGNED_INT, 0). Weil indices ein Uint32Array ist, braucht man in WebGL 1 dafür die Erweiterung OES_element_index_uint.
  • Die Koordinaten beziehen sich auf den jeweiligen View. Welches Koordinatensystem genau gilt und ob die projectionMatrix des Views angewendet werden muss, legt die Spezifikation fest. Das sollte man vor dem Einsatz dort nachlesen.
  • Die Maske kann sich während der Sitzung ändern, z. B. wenn der Linsenabstand verstellt wird. Gespeicherte Puffer müssen bei jedem Event ersetzt und die alten mit gl.deleteBuffer() freigegeben werden.
  • Ein leeres Array ist erlaubt. Dann einfach ohne Maske den ganzen View rendern.