Signatur
Beschreibung
beginRenderPass() eröffnet im GPUCommandEncoder einen Render-Pass. Das ist der Abschnitt, in dem die GPU mit Render-Pipelines in Texturen zeichnet. Über den Deskriptor legst du fest, wohin gezeichnet wird: in einen oder mehrere Farb-Anhänge (colorAttachments) und optional in einen Tiefen-/Stencil-Anhang (depthStencilAttachment). Außerdem bestimmst du, was am Anfang und am Ende des Passes mit den Inhalten geschieht: Mit loadOp werden sie geleert oder übernommen, mit storeOp gespeichert oder verworfen.
Der zurückgegebene GPURenderPassEncoder nimmt Befehle wie setPipeline(), setBindGroup(), setVertexBuffer() und draw() entgegen. Der Pass wird mit end() abgeschlossen. Erst danach kannst du den Command-Encoder weiterverwenden, etwa für einen weiteren Pass oder Kopierbefehle, oder ihn mit finish() in einen GPUCommandBuffer umwandeln und über device.queue.submit() absenden.
Typische Einsätze sind das Zeichnen eines Frames in den Canvas (über context.getCurrentTexture().createView()), das Rendern in eine Offscreen-Textur für Nachbearbeitungseffekte, Shadow-Maps (nur Tiefen-Anhang) und Multisampling mit resolveTarget.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $descriptor Pflicht | GPURenderPassDescriptor | Objekt, das den Render-Pass beschreibt. Mögliche Felder:
|
Rückgabewert
end() abgeschlossen werden.Beispiele
Canvas mit einer Farbe leeren und ein Dreieck zeichnen
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 module = device.createShaderModule({
code: `
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
let p = array(vec2f(0.0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5));
return vec4f(p[i], 0.0, 1.0);
}
@fragment fn fs() -> @location(0) vec4f {
return vec4f(1.0, 0.4, 0.0, 1.0);
}`
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs' },
fragment: { module, entryPoint: 'fs', targets: [{ format }] }
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
label: 'Hauptpass',
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: { r: 0.1, g: 0.1, b: 0.15, a: 1 },
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);
Render-Pass mit Tiefenpuffer
// Voraussetzung: device, context und format wie im ersten Beispiel
const depthTexture = device.createTexture({
size: [canvas.width, canvas.height],
format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: [0, 0, 0, 1],
loadOp: 'clear',
storeOp: 'store'
}],
depthStencilAttachment: {
view: depthTexture.createView(),
depthClearValue: 1.0,
depthLoadOp: 'clear',
depthStoreOp: 'store'
}
});
// Die Pipeline braucht depthStencil: { format: 'depth24plus', depthCompare: 'less', depthWriteEnabled: true }
// pass.setPipeline(pipeline3D); pass.draw(vertexCount);
pass.end();
device.queue.submit([encoder.finish()]);
4×-Multisampling mit resolveTarget
const msaaTexture = device.createTexture({
size: [canvas.width, canvas.height],
sampleCount: 4,
format,
usage: GPUTextureUsage.RENDER_ATTACHMENT
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: msaaTexture.createView(), // Multisample-Ziel
resolveTarget: context.getCurrentTexture().createView(), // geglättetes Ergebnis
clearValue: [1, 1, 1, 1],
loadOp: 'clear',
storeOp: 'discard' // MSAA-Daten werden nach dem Auflösen nicht mehr gebraucht
}]
});
// Die Pipeline braucht multisample: { count: 4 }
pass.end();
device.queue.submit([encoder.finish()]);