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

WebGLRenderingContext.scissor()

Methode

Legt eine rechteckige „Scissor Box“ fest, außerhalb derer Zeichen- und Löschoperationen verworfen werden, sofern <code>gl.SCISSOR_TEST</code> aktiv ist.

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

Signatur

WebGLRenderingContext.prototype.scissor(x, y, width, height)

Beschreibung

scissor() definiert ein Rechteck in Fensterkoordinaten (Pixel des Zeichenpuffers). Ist der Scissor-Test mit gl.enable(gl.SCISSOR_TEST) eingeschaltet, werden alle Fragmente außerhalb dieses Rechtecks verworfen. Das gilt für drawArrays()/drawElements() und auch für gl.clear().

Typische Einsatzfälle sind:

  • Nur einen Teilbereich des Canvas löschen oder neu zeichnen, etwa für Split-Screen-Ansichten oder mehrere Viewports in einem Canvas.
  • UI-Elemente beschneiden (Clipping), z. B. scrollbare Panels in einer WebGL-Oberfläche.
  • Die Leistung verbessern, weil nur der wirklich geänderte Bereich bearbeitet wird.

Der Ursprung (0, 0) liegt in der linken unteren Ecke des Zeichenpuffers, nicht links oben wie bei DOM oder Canvas 2D. Anders als viewport() verändert scissor() die Koordinatentransformation nicht. Die Methode schneidet nur ab. Deshalb nutzt man sie oft zusammen mit viewport() und denselben Werten.

Parameter

Name Typ Default Beschreibung
$x Pflicht number (GLint) 0 Horizontale Koordinate der linken unteren Ecke der Scissor Box in Pixeln.
$y Pflicht number (GLint) 0 Vertikale Koordinate der linken unteren Ecke, gemessen vom unteren Rand des Zeichenpuffers.
$width Pflicht number (GLsizei) Breite des Canvas Breite des Rechtecks in Pixeln. Ein negativer Wert erzeugt gl.INVALID_VALUE.
$height Pflicht number (GLsizei) Höhe des Canvas Höhe des Rechtecks in Pixeln. Ein negativer Wert erzeugt gl.INVALID_VALUE.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Nur einen Teilbereich löschen

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

// Gesamten Canvas schwarz löschen
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

// Scissor-Test aktivieren und ein 100×50-Rechteck rot löschen
gl.enable(gl.SCISSOR_TEST);
gl.scissor(20, 20, 100, 50);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.disable(gl.SCISSOR_TEST);

Aktuelle Scissor Box auslesen

const gl = document.createElement('canvas').getContext('webgl');
gl.scissor(10, 20, 64, 32);

const box = gl.getParameter(gl.SCISSOR_BOX); // Int32Array
console.log(Array.from(box));
console.log(gl.isEnabled(gl.SCISSOR_TEST));
[10, 20, 64, 32] false

Split-Screen: zwei Ansichten in einem Canvas

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const w = gl.drawingBufferWidth;
const h = gl.drawingBufferHeight;

const renderView = (x, y, width, height, color) => {
  gl.viewport(x, y, width, height); // Transformation
  gl.scissor(x, y, width, height);  // Beschneidung
  gl.clearColor(...color, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  // hier z. B. gl.drawArrays(...) für die jeweilige Kamera
};

gl.enable(gl.SCISSOR_TEST);
renderView(0, 0, w / 2, h, [0.2, 0.3, 0.8]);     // linke Hälfte
renderView(w / 2, 0, w / 2, h, [0.8, 0.3, 0.2]); // rechte Hälfte
gl.disable(gl.SCISSOR_TEST);

DOM-Koordinaten (oben links) umrechnen

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

// Rechteck in CSS-Pixeln relativ zur linken oberen Ecke
const setScissorFromDom = ({ left, top, width, height }) => {
  const dpr = window.devicePixelRatio || 1;
  const bufH = gl.drawingBufferHeight;
  gl.scissor(
    Math.round(left * dpr),
    Math.round(bufH - (top + height) * dpr), // Y-Achse umkehren
    Math.round(width * dpr),
    Math.round(height * dpr)
  );
};

gl.enable(gl.SCISSOR_TEST);
setScissorFromDom({ left: 10, top: 10, width: 120, height: 80 });
gl.clearColor(0, 1, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

// Wichtig · Fallstricke

  • Ohne gl.enable(gl.SCISSOR_TEST) hat scissor() keine Wirkung. Der Test ist standardmäßig ausgeschaltet. Das ist der häufigste Fehler.
  • Die Scissor Box wirkt auch auf gl.clear(), viewport() dagegen nicht. Wer nur einen Bereich löschen will, braucht deshalb scissor().
  • Der Ursprung liegt links unten. DOM- oder Mauskoordinaten müssen an der Y-Achse gespiegelt und mit devicePixelRatio skaliert werden.
  • Die Scissor Box bleibt als Zustand des Kontexts erhalten, bis sie geändert wird. Nach dem Beschneiden solltest du den Test wieder abschalten, sonst werden spätere Zeichenaufrufe unbemerkt abgeschnitten.
  • Negative Werte für width/height erzeugen gl.INVALID_VALUE (prüfbar mit gl.getError()). Negative x/y sind dagegen erlaubt.
  • Der Anfangswert ist (0, 0, Canvasbreite, Canvashöhe). Ändert sich die Canvasgröße, passt sich die Scissor Box nicht automatisch an.
  • Die Methode gibt es genauso in WebGL2RenderingContext. Sie wird in allen modernen Browsern unterstützt.