Signatur
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
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);
}
// Wichtig · Fallstricke
- Validierung: Es muss gelten
x + width ≤ Breiteundy + height ≤ Höhedes Render-Ziels. Andernfalls wird ein Validierungsfehler erzeugt, der Encoder wird ungültig undfinish()/submit()schlägt fehl – Werte also vorher begrenzen. - Nachkommastellen werden gemäß WebIDL (
GPUIntegerCoordinate) abgeschnitten; negative Werte führen zu einemTypeError. MitMath.floor/Math.ceilexplizit runden. - Ein Rechteck mit Breite oder Höhe
0ist 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
devicePixelRatioumrechnen. - Der Zustand wird bei jedem neuen Render-Pass zurückgesetzt und nicht über Render-Bundles hinweg übernommen; in
GPURenderBundleEncodergibt es keinesetScissorRect()-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.