Start · Sprachen · JavaScript · Referenz · GPURenderPassEncoder.setScissorRect()

GPURenderPassEncoder.setScissorRect()

Methode

Legt das Scherrechteck (Scissor-Rechteck) eines Render-Passes fest: Fragmente außerhalb dieses Pixelbereichs werden bei der Rasterisierung verworfen.

seit JavaScript WebGPU – Chrome/Edge 113+, Firefox 141+ (Windows), Kategorie: webapi

Signatur

GPURenderPassEncoder.prototype.setScissorRect(x, y, width, height)

Beschreibung

setScissorRect() beschränkt alle nachfolgenden Zeichenbefehle eines GPURenderPassEncoder auf einen rechteckigen Bereich des Render-Ziels. Fragmente, die außerhalb dieses Rechtecks liegen, werden verworfen, noch bevor der Fragment-Shader Farbe, Tiefe oder Stencil schreibt. Die Koordinaten sind ganzzahlige Pixelkoordinaten des Framebuffers, der Ursprung (0, 0) liegt oben links.

Typische Einsatzfälle sind UI-Rendering mit Clipping (z. B. scrollbare Panels in Dear-ImGui-ähnlichen Oberflächen), Split-Screen-Darstellungen, Bild-in-Bild-Ansichten oder das gezielte Neuzeichnen nur eines geänderten Teilbereichs. Anders als setViewport() skaliert das Scherrechteck die Geometrie nicht, sondern schneidet nur ab.

Zu Beginn jedes Render-Passes umfasst das Scherrechteck automatisch das gesamte Render-Ziel. Der Zustand gilt nur innerhalb des aktuellen Passes und bleibt bis zum nächsten Aufruf von setScissorRect() bzw. bis end() bestehen. Beachte: Das Scherrechteck wirkt nicht auf die Clear-Operation (loadOp: "clear") – diese löscht immer das ganze Attachment.

Parameter

Name Typ Default Beschreibung
$x Pflicht number (GPUIntegerCoordinate) Horizontale Pixelposition der linken Kante des Rechtecks.
$y Pflicht number (GPUIntegerCoordinate) Vertikale Pixelposition der oberen Kante des Rechtecks (Ursprung oben links).
$width Pflicht number (GPUIntegerCoordinate) Breite des Rechtecks in Pixeln.
$height Pflicht number (GPUIntegerCoordinate) Höhe des Rechtecks in Pixeln.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Befehl wird in den Render-Pass aufgezeichnet.

Beispiele

Zeichnen auf die linke Bildschirmhälfte beschränken

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
context.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });

// pipeline wurde zuvor mit device.createRenderPipeline() erzeugt
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
  colorAttachments: [{
    view: context.getCurrentTexture().createView(),
    clearValue: { r: 0, g: 0, b: 0, a: 1 },
    loadOp: 'clear',
    storeOp: 'store'
  }]
});

pass.setPipeline(pipeline);
// Nur die linke Hälfte des Canvas wird beschrieben
pass.setScissorRect(0, 0, Math.floor(canvas.width / 2), canvas.height);
pass.draw(3);
pass.end();

device.queue.submit([encoder.finish()]);

Split-Screen mit Viewport und Scissor

const halfW = Math.floor(canvas.width / 2);
const h = canvas.height;

const views = [
  { x: 0, bindGroup: playerOneBindGroup },
  { x: halfW, bindGroup: playerTwoBindGroup }
];

pass.setPipeline(pipeline);
for (const { x, bindGroup } of views) {
  // Viewport skaliert die Szene, Scissor schneidet sauber ab
  pass.setViewport(x, 0, halfW, h, 0, 1);
  pass.setScissorRect(x, 0, halfW, h);
  pass.setBindGroup(0, bindGroup);
  pass.draw(vertexCount);
}
pass.end();

UI-Clipping mit sicherem Begrenzen der Werte

// Clip-Rechteck eines UI-Panels (evtl. teilweise außerhalb des Canvas)
const clampScissor = (rect, targetW, targetH) => {
  const x = Math.max(0, Math.floor(rect.x));
  const y = Math.max(0, Math.floor(rect.y));
  const right = Math.min(targetW, Math.ceil(rect.x + rect.width));
  const bottom = Math.min(targetH, Math.ceil(rect.y + rect.height));
  return [x, y, Math.max(0, right - x), Math.max(0, bottom - y)];
};

const panel = { x: -20.5, y: 40, width: 300, height: 5000 };
const [sx, sy, sw, sh] = clampScissor(panel, canvas.width, canvas.height);
console.log(sx, sy, sw, sh);

if (sw > 0 && sh > 0) {
  pass.setScissorRect(sx, sy, sw, sh);
  pass.drawIndexed(panelIndexCount);
}
0 40 280 1040 // bei einem 1920×1080-Canvas

// Wichtig · Fallstricke

  • Validierung: Es muss gelten x + width ≤ Breite und y + height ≤ Höhe des Render-Ziels. Andernfalls wird ein Validierungsfehler erzeugt, der Encoder wird ungültig und finish()/submit() schlägt fehl – Werte also vorher begrenzen.
  • Nachkommastellen werden gemäß WebIDL (GPUIntegerCoordinate) abgeschnitten; negative Werte führen zu einem TypeError. Mit Math.floor/Math.ceil explizit runden.
  • Ein Rechteck mit Breite oder Höhe 0 ist zulässig – dann wird schlicht nichts gezeichnet.
  • Achtung bei hochauflösenden Displays: Die Koordinaten beziehen sich auf Texturpixel, nicht auf CSS-Pixel. UI-Koordinaten mit devicePixelRatio umrechnen.
  • Der Zustand wird bei jedem neuen Render-Pass zurückgesetzt und nicht über Render-Bundles hinweg übernommen; in GPURenderBundleEncoder gibt es keine setScissorRect()-Methode.
  • WebGPU steht nur in sicheren Kontexten (HTTPS) zur Verfügung und wird noch nicht von allen Browsern/Plattformen unterstützt – vorher mit if (!navigator.gpu) prüfen.