Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.depthMask()

WebGLRenderingContext.depthMask()

Methode

Legt fest, ob beim Zeichnen Werte in den Tiefenpuffer geschrieben werden (<code>true</code>) oder ob der Tiefenpuffer schreibgeschützt ist (<code>false</code>).

seit JavaScript Baseline: alle Browser (WebGL 1) Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.depthMask(flag)

Beschreibung

Mit depthMask() legst du fest, ob Fragmente, die den Tiefentest bestehen, ihren Tiefenwert in den Tiefenpuffer schreiben. Der Tiefentest selbst wird davon nicht beeinflusst. Er wird über gl.enable(gl.DEPTH_TEST) und gl.depthFunc() gesteuert. Mit depthMask(false) werden Fragmente also weiterhin gegen den vorhandenen Tiefenpuffer geprüft, verändern ihn aber nicht.

Typischer Einsatz ist das Zeichnen transparenter Objekte: Zuerst zeichnest du alle undurchsichtigen Objekte mit aktivem Tiefenschreiben. Danach zeichnest du die transparenten Objekte mit depthMask(false). So werden sie korrekt von undurchsichtiger Geometrie verdeckt, verdecken sich aber nicht gegenseitig im Tiefenpuffer. Weitere Anwendungen sind Skyboxen, Partikelsysteme, Overlays und HUD-Elemente.

Die Einstellung ist ein globaler Zustand des Kontexts. Sie gilt, bis sie erneut geändert wird. Außerdem beeinflusst sie auch gl.clear(gl.DEPTH_BUFFER_BIT): Bei depthMask(false) wird der Tiefenpuffer beim Löschen nicht zurückgesetzt. Den aktuellen Wert fragst du mit gl.getParameter(gl.DEPTH_WRITEMASK) ab.

Parameter

Name Typ Default Beschreibung
$flag Pflicht boolean true true aktiviert das Schreiben in den Tiefenpuffer, false deaktiviert es. Der Anfangswert im Kontext ist true.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Tiefenschreiben ein- und ausschalten und Zustand abfragen

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');

console.log(gl.getParameter(gl.DEPTH_WRITEMASK)); // Standardwert

gl.depthMask(false);
console.log(gl.getParameter(gl.DEPTH_WRITEMASK));

gl.depthMask(true);
console.log(gl.getParameter(gl.DEPTH_WRITEMASK));
true false true

Undurchsichtige und transparente Objekte in zwei Durchgängen rendern

// Annahme: drawMesh(mesh) bindet Buffer und ruft gl.drawArrays/drawElements auf
const renderFrame = (gl, opaqueMeshes, transparentMeshes, cameraPos) => {
  gl.enable(gl.DEPTH_TEST);
  gl.depthFunc(gl.LEQUAL);

  // Wichtig: vor clear() Tiefenschreiben aktivieren, sonst wird der Tiefenpuffer nicht gelöscht
  gl.depthMask(true);
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // 1. Durchgang: undurchsichtig, mit Tiefenschreiben
  gl.disable(gl.BLEND);
  opaqueMeshes.forEach(drawMesh);

  // 2. Durchgang: transparent, von hinten nach vorne, ohne Tiefenschreiben
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  gl.depthMask(false);

  const dist = (m) => Math.hypot(
    m.position[0] - cameraPos[0],
    m.position[1] - cameraPos[1],
    m.position[2] - cameraPos[2]
  );
  [...transparentMeshes]
    .sort((a, b) => dist(b) - dist(a))
    .forEach(drawMesh);

  // Zustand zurücksetzen
  gl.depthMask(true);
  gl.disable(gl.BLEND);
};

Skybox zeichnen, ohne den Tiefenpuffer zu verändern

const drawSkybox = (gl, skyboxProgram, drawCube) => {
  gl.useProgram(skyboxProgram);
  gl.depthMask(false);      // Skybox soll nichts verdecken
  drawCube();
  gl.depthMask(true);       // danach normale Szene zeichnen
};

// Wichtig · Fallstricke

  • Häufiger Fehler: Wenn depthMask(false) noch aktiv ist, löscht gl.clear(gl.DEPTH_BUFFER_BIT) den Tiefenpuffer nicht. Aktiviere vor dem Löschen deshalb immer depthMask(true).
  • depthMask() schaltet den Tiefentest nicht ab. Um ihn ganz zu umgehen, verwendest du gl.disable(gl.DEPTH_TEST). Ist DEPTH_TEST deaktiviert, wird übrigens auch nicht in den Tiefenpuffer geschrieben.
  • Das Ausschalten des Tiefenschreibens bei transparenten Objekten löst das Sortierproblem nicht vollständig. Für korrektes Überblenden solltest du trotzdem von hinten nach vorne zeichnen oder ordnungsunabhängige Transparenz verwenden.
  • Der Kontext braucht einen Tiefenpuffer. Die Option depth in getContext('webgl', { depth: true }) ist standardmäßig true. Bei false hat die Methode keine sichtbare Wirkung.
  • Die Methode steht genauso in WebGL2RenderingContext zur Verfügung. Sie wird in allen modernen Browsern unterstützt.
  • Die Methode entspricht glDepthMask aus OpenGL ES 2.0.