Signatur
Beschreibung
Mit setBlendConstant() legst du für den laufenden Render-Durchgang eine konstante Farbe fest, auf die die Blend-Stufe zugreifen kann. Diese Konstante wird nur ausgewertet, wenn im blend-Abschnitt eines Farbziels im Pipeline-Deskriptor (fragment.targets[i].blend) als srcFactor oder dstFactor der Wert "constant" oder "one-minus-constant" steht.
Typische Anwendungsfälle sind Überblendungen mit einem festen Mischverhältnis (z. B. eine Szene zu 30 % über eine andere legen), Einfärben mit einer Tönungsfarbe oder das Ein- und Ausblenden ganzer Ebenen, ohne dafür einen Uniform-Buffer zu ändern oder die Pipeline neu zu erstellen. Weil die Konstante ein dynamischer Zustand des Encoders ist, kann dieselbe Pipeline mit verschiedenen Konstanten mehrfach im selben Durchgang benutzt werden.
Die Konstante gilt ab dem Aufruf für alle nachfolgenden Draw-Aufrufe im selben GPURenderPassEncoder, bis sie erneut gesetzt wird. Zu Beginn jedes Render-Durchgangs ist sie [0, 0, 0, 0]. Bei "constant" wird für die Farbkomponenten der RGB-Anteil und für den Alpha-Kanal der Alpha-Anteil der Konstante genutzt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $color Pflicht | GPUColor (Array<number> der Länge 4 | {r: number, g: number, b: number, a: number}) | Die Blendkonstante als Rot-, Grün-, Blau- und Alpha-Anteil, normalerweise im Bereich 0.0–1.0. Entweder als Array [r, g, b, a] oder als Objekt { r, g, b, a }. |
Rückgabewert
Beispiele
Pipeline mit konstantem Blendfaktor anlegen und Konstante setzen
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const format = navigator.gpu.getPreferredCanvasFormat();
const context = document.querySelector('canvas').getContext('webgpu');
context.configure({ device, format });
const module = device.createShaderModule({
code: `
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
var p = array(vec2f(0, 0.8), vec2f(-0.8, -0.8), vec2f(0.8, -0.8));
return vec4f(p[i], 0, 1);
}
@fragment fn fs() -> @location(0) vec4f { return vec4f(1, 0.5, 0, 1); }
`
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module, entryPoint: 'vs' },
fragment: {
module,
entryPoint: 'fs',
targets: [{
format,
blend: {
// Ergebnis = Quelle * Konstante + Ziel * (1 - Konstante)
color: { srcFactor: 'constant', dstFactor: 'one-minus-constant', operation: 'add' },
alpha: { srcFactor: 'one', dstFactor: 'zero', operation: 'add' }
}
}]
}
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
clearValue: [0, 0, 0.3, 1],
loadOp: 'clear',
storeOp: 'store'
}]
});
pass.setPipeline(pipeline);
// Dreieck zu 40 % über den Hintergrund mischen
pass.setBlendConstant([0.4, 0.4, 0.4, 1]);
pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);
Dieselbe Pipeline mit unterschiedlichen Konstanten zeichnen
// Annahme: pipeline, pass und vertexBuffer existieren bereits (siehe oben)
const opacities = [0.2, 0.5, 0.8];
pass.setPipeline(pipeline);
pass.setVertexBuffer(0, vertexBuffer);
opacities.forEach((o, i) => {
// Objekt-Schreibweise ist ebenfalls erlaubt
pass.setBlendConstant({ r: o, g: o, b: o, a: 1 });
pass.draw(3, 1, i * 3); // jeweils ein anderes Dreieck
});
pass.end();
Animiertes Überblenden pro Frame
const frame = (time) => {
const t = (Math.sin(time / 1000) + 1) / 2; // 0 … 1
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
loadOp: 'clear', storeOp: 'store', clearValue: [0, 0, 0, 1]
}]
});
pass.setPipeline(pipeline);
pass.setBlendConstant([t, t, t, 1]); // Konstante muss in jedem Durchgang neu gesetzt werden
pass.draw(3);
pass.end();
device.queue.submit([encoder.finish()]);
requestAnimationFrame(frame);
};
requestAnimationFrame(frame);
// Wichtig · Fallstricke
- Wirkung nur mit passendem Blendfaktor: Ohne
"constant"oder"one-minus-constant"imblend-Deskriptor der aktiven Pipeline hat der Aufruf keine sichtbare Wirkung. - Zurücksetzen pro Durchgang: Die Konstante wird bei jedem
beginRenderPass()auf[0, 0, 0, 0]gesetzt. Wenn du sie vergisst, sieht die Quelle bei"constant"komplett transparent bzw. schwarz aus. - Werte außerhalb von 0–1: Bei normalisierten Formaten (z. B.
bgra8unorm) wird auf den gültigen Bereich begrenzt. Nur Float-Ziele wiergba16floatkönnen größere Werte sinnvoll nutzen. - Ein Array mit einer anderen Länge als 4 löst einen
TypeErroraus. Wenn der Encoder schon mitend()beendet wurde, entsteht ein Validierungsfehler. - Kompatibilität: WebGPU gibt es nur im sicheren Kontext. Die Unterstützung ist noch nicht in allen Browsern bzw. auf allen Plattformen vollständig. Prüfe daher vorher mit
if (!navigator.gpu)und sieh eine Ausweichlösung vor.