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

WebGLRenderingContext.stencilFunc()

Methode

Legt Vergleichsfunktion, Referenzwert und Bitmaske des Stencil-Tests für Vorder- und Rückseiten gleichzeitig fest.

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

Signatur

WebGLRenderingContext.prototype.stencilFunc(func, ref, mask)

Beschreibung

stencilFunc() bestimmt, wann ein Fragment den Stencil-Test besteht. Für jedes Fragment wird (ref & mask) über die gewählte Vergleichsfunktion mit (stencilWert & mask) verglichen. stencilWert ist dabei der Wert, der an dieser Pixelposition schon im Stencil-Puffer steht. Besteht das Fragment den Test nicht, wird es verworfen.

Die Methode gilt für Vorder- und Rückseiten zugleich. Brauchen Sie für beide Seiten unterschiedliche Einstellungen, zum Beispiel für Stencil-Schatten-Volumen, nehmen Sie stencilFuncSeparate().

Typische Einsatzgebiete sind Masken (nur innerhalb einer bestimmten Form zeichnen), Umrisse bei ausgewählten Objekten, Spiegelungen und Portale. Meist kombinieren Sie die Methode mit stencilOp() (was bei bestandenem oder nicht bestandenem Test in den Puffer geschrieben wird) und mit stencilMask() (welche Bits überhaupt beschrieben werden dürfen).

Wichtig: Der Stencil-Test wirkt nur, wenn er mit gl.enable(gl.STENCIL_TEST) eingeschaltet ist und der Zeichenpuffer einen Stencil-Puffer hat. Den bekommen Sie mit getContext('webgl', { stencil: true }) oder mit einem Framebuffer, an den ein DEPTH_STENCIL- bzw. STENCIL_INDEX8-Renderbuffer angehängt ist.

Parameter

Name Typ Default Beschreibung
$func Pflicht GLenum gl.ALWAYS Vergleichsfunktion: gl.NEVER, gl.LESS, gl.EQUAL, gl.LEQUAL, gl.GREATER, gl.NOTEQUAL, gl.GEQUAL oder gl.ALWAYS. Verglichen wird in der Form (ref & mask) OP (stencil & mask). gl.LESS bedeutet also: Der Test besteht, wenn der Referenzwert kleiner ist als der gespeicherte Wert.
$ref Pflicht GLint 0 Referenzwert für den Vergleich. Er wird auf den Bereich 0 bis 2n−1 begrenzt, wobei n die Anzahl der Stencil-Bits ist (meist 8).
$mask Pflicht GLuint 0xFFFFFFFF (alle Bits gesetzt) Bitmaske, die vor dem Vergleich per UND auf ref und auf den gespeicherten Stencil-Wert angewendet wird. Häufig ist das 0xFF.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Kontext mit Stencil-Puffer anlegen und Test aktivieren

const canvas = document.querySelector('canvas');
// Ohne stencil: true gibt es meist keinen Stencil-Puffer
const gl = canvas.getContext('webgl', { stencil: true });

console.log('Stencil-Bits:', gl.getParameter(gl.STENCIL_BITS));

gl.enable(gl.STENCIL_TEST);
gl.clearStencil(0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

// Jedes Fragment besteht den Test
gl.stencilFunc(gl.ALWAYS, 1, 0xFF);

console.log(gl.getParameter(gl.STENCIL_FUNC) === gl.ALWAYS);
console.log(gl.getParameter(gl.STENCIL_REF));
Stencil-Bits: 8 true 1

Maske zeichnen, danach nur innerhalb der Maske rendern

// Voraussetzung: gl mit { stencil: true }, drawCircle() und drawScene() sind eigene Zeichenfunktionen
gl.enable(gl.STENCIL_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

// Durchgang 1: Kreis nur in den Stencil-Puffer schreiben (Wert 1)
gl.colorMask(false, false, false, false);
gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
gl.stencilMask(0xFF);
drawCircle();

// Durchgang 2: Szene nur dort zeichnen, wo der Stencil-Wert 1 ist
gl.colorMask(true, true, true, true);
gl.stencilFunc(gl.EQUAL, 1, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
gl.stencilMask(0x00); // Puffer nicht mehr verändern
drawScene();

Umriss um ein ausgewähltes Objekt

// Objekt normal zeichnen und seine Fläche mit 1 markieren
gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
gl.stencilMask(0xFF);
drawObject(1.0);

// Leicht vergrößerte Version nur außerhalb der markierten Fläche zeichnen
gl.stencilFunc(gl.NOTEQUAL, 1, 0xFF);
gl.stencilMask(0x00);
gl.disable(gl.DEPTH_TEST);
drawObjectOutline(1.05); // einfarbiger Shader
gl.enable(gl.DEPTH_TEST);
gl.stencilMask(0xFF);

// Wichtig · Fallstricke

  • Kein Stencil-Puffer: Standardmäßig ist stencil in den Kontext-Attributen false. Dann hat stencilFunc() keine sichtbare Wirkung. Prüfen Sie das mit gl.getContextAttributes().stencil oder gl.getParameter(gl.STENCIL_BITS).
  • Der Test läuft nur, wenn gl.STENCIL_TEST aktiviert ist. Die Einstellungen bleiben aber auch ohne aktivierten Test gespeichert.
  • Reihenfolge beim Vergleich: Links steht der Referenzwert. gl.LESS heißt also ref < stencil und nicht umgekehrt. Das wird oft verwechselt.
  • Ein ungültiger Wert für func löst den Fehler gl.INVALID_ENUM aus. Abfragen können Sie ihn mit gl.getError().
  • In WebGL müssen die Stencil-Einstellungen (ref, mask, writemask) für Vorder- und Rückseite übereinstimmen. Sonst meldet ein Zeichenaufruf INVALID_OPERATION. Das ist vor allem bei stencilFuncSeparate() wichtig.
  • Die aktuellen Werte fragen Sie mit getParameter() ab: STENCIL_FUNC, STENCIL_REF, STENCIL_VALUE_MASK sowie die STENCIL_BACK_*-Gegenstücke.
  • In WebGL2RenderingContext gibt es die Methode ebenfalls. Alle modernen Browser unterstützen sie.