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

GPURenderPassEncoder.setViewport()

Methode

Legt den Viewport fest, mit dem der Rasterizer normalisierte Gerätekoordinaten (NDC) linear in Viewport- bzw. Pixelkoordinaten und in einen Tiefenbereich umrechnet.

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

Signatur

GPURenderPassEncoder.prototype.setViewport(x, y, width, height, minDepth, maxDepth)

Beschreibung

setViewport() bestimmt, auf welchen rechteckigen Bereich der Render-Attachments die Ausgabe des Vertex-Shaders abgebildet wird. Die Clip-Space-Koordinaten (nach der perspektivischen Division im Bereich -1 bis 1 für x/y und 0 bis 1 für z) werden linear auf das Rechteck (x, y, width, height) in Pixeln und auf den Tiefenbereich minDepth bis maxDepth umgerechnet.

Typische Einsatzfälle sind Split-Screen-Ansichten (mehrere Kameras in einem Render-Pass), Minimaps und Bild-in-Bild-Darstellungen, das Rendern in einzelne Kacheln eines Texture-Atlas (z. B. Shadow-Map-Atlas) oder das Beschränken des Tiefenbereichs, etwa um ein Skybox- oder HUD-Element immer vorn bzw. hinten darzustellen.

Ohne Aufruf gilt standardmäßig ein Viewport, der das gesamte Attachment abdeckt, mit Tiefenbereich 0 bis 1. Der gesetzte Wert bleibt bis zum nächsten Aufruf von setViewport() oder bis zum Ende des Render-Passes gültig und betrifft alle folgenden Zeichenbefehle. Beachte: Der Viewport skaliert die Geometrie – er schneidet nicht ab. Zum reinen Abschneiden ohne Skalierung dient setScissorRect().

Parameter

Name Typ Default Beschreibung
$x Pflicht number Minimaler X-Wert (linke Kante) des Viewports in Pixeln. Gleitkommawerte sind erlaubt.
$y Pflicht number Minimaler Y-Wert (obere Kante) des Viewports in Pixeln. In WebGPU liegt der Ursprung oben links.
$width Pflicht number Breite des Viewports in Pixeln, muss ≥ 0 sein.
$height Pflicht number Höhe des Viewports in Pixeln, muss ≥ 0 sein.
$minDepth Pflicht number Minimaler Tiefenwert, im Bereich 0.0 bis 1.0 und ≤ maxDepth.
$maxDepth Pflicht number Maximaler Tiefenwert, im Bereich 0.0 bis 1.0 und ≥ minDepth.

Rückgabewert

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

Beispiele

Viewport explizit auf die ganze Canvas setzen

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

const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
  colorAttachments: [{
    view: context.getCurrentTexture().createView(),
    clearValue: { r: 0.1, g: 0.1, b: 0.1, a: 1 },
    loadOp: 'clear',
    storeOp: 'store'
  }]
});

// Entspricht dem Standard-Viewport
pass.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
// pass.setPipeline(pipeline); pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);

Split-Screen: zwei Kameras in einem Render-Pass

// Annahme: pipeline, device, canvas, pass wie oben;
// bindGroupLeft/bindGroupRight enthalten je eine eigene Kamera-Matrix
const halfWidth = canvas.width / 2;

pass.setPipeline(pipeline);

// Linke Hälfte – Spieler 1
pass.setViewport(0, 0, halfWidth, canvas.height, 0, 1);
pass.setBindGroup(0, bindGroupLeft);
pass.draw(36);

// Rechte Hälfte – Spieler 2
pass.setViewport(halfWidth, 0, halfWidth, canvas.height, 0, 1);
pass.setBindGroup(0, bindGroupRight);
pass.draw(36);

pass.end();

Minimap mit Viewport und Scissor sowie Tiefenbereich

const size = 200;
const margin = 16;
const x = canvas.width - size - margin;
const y = margin;

// Hauptszene
pass.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
pass.setBindGroup(0, mainCamera);
pass.draw(vertexCount);

// Minimap oben rechts; Tiefenbereich 0–0.1, damit sie vor der Szene liegt
pass.setViewport(x, y, size, size, 0, 0.1);
pass.setScissorRect(x, y, size, size); // Clear/Zeichnung auf Bereich begrenzen
pass.setBindGroup(0, topDownCamera);
pass.draw(vertexCount);

// Wichtig · Fallstricke

  • Validierung: Verletzen die Werte die Regeln (width/height < 0, minDepth/maxDepth außerhalb von 0–1, minDepth > maxDepth, Viewport außerhalb der erlaubten Grenzen von maxTextureDimension2D), wird kein Fehler geworfen: Der Encoder wird ungültig, und der Fehler erscheint erst bei finish()/submit() als Validierungsfehler (z. B. über device.pushErrorScope('validation') oder die Konsole).
  • Koordinatensystem: Anders als in WebGL liegt der Ursprung oben links, und y wächst nach unten. Aus WebGL portierter Code, der gl.viewport() mit Ursprung unten links nutzt, muss angepasst werden.
  • Viewport ≠ Scissor: Der Viewport skaliert die Geometrie; Fragmente außerhalb des Attachments werden zwar verworfen, ein Clear über loadOp: 'clear' betrifft aber immer das gesamte Attachment. Zum Begrenzen setScissorRect() zusätzlich verwenden.
  • Canvas-Größe: Nutze canvas.width/canvas.height (Pixelpuffer), nicht die CSS-Größe – sonst stimmt der Viewport bei devicePixelRatio ≠ 1 nicht.
  • Der Zustand gilt nur für den aktuellen Render-Pass; jeder neue Pass beginnt wieder mit dem Standard-Viewport.
  • Kompatibilität: WebGPU erfordert einen sicheren Kontext (HTTPS) und ist noch nicht in allen Browsern/Plattformen verfügbar – vorher auf navigator.gpu prüfen.