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

WebGLRenderingContext.stencilMaskSeparate()

Methode

Legt getrennt für Vorder- und/oder Rückseiten fest, welche Bits des Stencil-Puffers beim Zeichnen beschrieben werden dürfen.

seit JavaScript WebGL 1.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.stencilMaskSeparate(face, mask)

Beschreibung

Die Methode stencilMaskSeparate() setzt eine Bitmaske, die bestimmt, welche Bits der Stencil-Ebenen (Schablonenpuffer) durch Stencil-Operationen verändert werden dürfen. Ein gesetztes Bit (1) erlaubt das Schreiben, ein gelöschtes Bit (0) schützt das entsprechende Bit vor Änderungen. Im Unterschied zu stencilMask() kann die Maske hier getrennt für vorder- und rückseitige Polygone angegeben werden.

Das ist vor allem bei Techniken nützlich, die Vorder- und Rückseiten im selben Zeichendurchgang unterschiedlich behandeln, etwa bei Stencil-Schattenvolumen (Z-Pass/Z-Fail) oder beim Markieren von Bereichen, die sich in mehreren Bitebenen überlagern. Welche Fläche als „vorne“ gilt, richtet sich nach frontFace() (Standard: gl.CCW).

Die Maske wirkt auf alle Schreibvorgänge in den Stencil-Puffer – also auf Operationen, die mit stencilOp()/stencilOpSeparate() festgelegt wurden, und auf gl.clear(gl.STENCIL_BUFFER_BIT). Der Standardwert ist „alle Bits beschreibbar“ (alle Einsen). Den aktuellen Wert fragt man mit gl.getParameter(gl.STENCIL_WRITEMASK) bzw. gl.STENCIL_BACK_WRITEMASK ab.

Parameter

Name Typ Default Beschreibung
$face Pflicht GLenum Für welche Flächen die Maske gilt: gl.FRONT, gl.BACK oder gl.FRONT_AND_BACK.
$mask Pflicht GLuint (number) Bitmaske, die das Schreiben einzelner Stencil-Bits erlaubt (1) oder verhindert (0). Standard ist 0xFFFFFFFF (alle Bits beschreibbar).

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Grundlegende Verwendung und Abfrage

const canvas = document.createElement('canvas');
// Stencil-Puffer muss explizit angefordert werden
const gl = canvas.getContext('webgl', { stencil: true });

// Vorderseiten dürfen nur die unteren 4 Bits schreiben
gl.stencilMaskSeparate(gl.FRONT, 0x0F);
// Rückseiten dürfen nur die oberen 4 Bits schreiben
gl.stencilMaskSeparate(gl.BACK, 0xF0);

console.log(gl.getParameter(gl.STENCIL_WRITEMASK).toString(16));
console.log(gl.getParameter(gl.STENCIL_BACK_WRITEMASK).toString(16));
f f0

Stencil-Schattenvolumen (Z-Fail) in einem Durchgang

const gl = document.querySelector('canvas').getContext('webgl', { stencil: true, depth: true });

const drawShadowVolume = (drawVolume) => {
  gl.enable(gl.STENCIL_TEST);
  gl.disable(gl.CULL_FACE);          // beide Seiten zeichnen
  gl.colorMask(false, false, false, false);
  gl.depthMask(false);

  // Beide Seiten dürfen alle 8 Bits schreiben
  gl.stencilMaskSeparate(gl.FRONT_AND_BACK, 0xFF);
  gl.stencilFunc(gl.ALWAYS, 0, 0xFF);
  gl.stencilOpSeparate(gl.BACK, gl.KEEP, gl.INCR_WRAP, gl.KEEP);
  gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.DECR_WRAP, gl.KEEP);

  drawVolume();

  gl.colorMask(true, true, true, true);
  gl.depthMask(true);
};

drawShadowVolume(() => { /* gl.drawArrays(...) für das Schattenvolumen */ });

Bits beim Löschen schützen

const gl = document.querySelector('canvas').getContext('webgl', { stencil: true });

// Bit 7 enthält eine dauerhafte Maske (z. B. UI-Bereich) und soll erhalten bleiben
gl.stencilMaskSeparate(gl.FRONT_AND_BACK, 0x7F);
gl.clearStencil(0);
gl.clear(gl.STENCIL_BUFFER_BIT); // löscht nur die Bits 0–6

// Danach wieder alle Bits freigeben
gl.stencilMaskSeparate(gl.FRONT_AND_BACK, 0xFF);

// Wichtig · Fallstricke

  • Stencil-Puffer anfordern: Ohne getContext('webgl', { stencil: true }) gibt es in der Regel keinen Stencil-Puffer (gl.getParameter(gl.STENCIL_BITS) liefert dann 0) – die Maske hat dann keine Wirkung.
  • WebGL-Einschränkung: Anders als in OpenGL ES verlangt WebGL, dass Vorder- und Rückseiten-Schreibmaske (sowie Referenzwert und Vergleichsmaske aus stencilFuncSeparate()) beim Zeichnen gleich sind, bezogen auf die tatsächlich vorhandenen Stencil-Bits. Sonst löst drawArrays()/drawElements() den Fehler gl.INVALID_OPERATION aus. Unterschiedliche Masken wie im ersten Beispiel sind also zwar setzbar, aber nicht zum Zeichnen verwendbar.
  • Ein ungültiger Wert für face erzeugt gl.INVALID_ENUM (prüfbar mit gl.getError()).
  • Die Maske beeinflusst auch gl.clear() – ein vergessenes Zurücksetzen führt oft zu „nicht gelöschten“ Stencil-Werten.
  • Verfügbar in allen modernen Browsern, ebenso in WebGL2RenderingContext.