Signatur
Beschreibung
drawBuffers() bestimmt, welchen Farbpuffern die einzelnen Ausgabevariablen des Fragment-Shaders zugeordnet werden. Der Index im übergebenen Array entspricht dem layout(location = n) der out-Variablen im GLSL-ES-3.00-Shader. So kann ein einziger Zeichenaufruf gleichzeitig in mehrere Texturen schreiben (Multiple Render Targets, MRT).
Typische Anwendung ist Deferred Shading: Ein G-Buffer-Durchlauf schreibt Albedo, Normalen und Positionen in einem Schritt in verschiedene Texturen, die ein späterer Beleuchtungsdurchlauf ausliest. Auch Picking (Farbe + Objekt-ID) oder Post-Processing-Effekte mit mehreren Zwischenergebnissen nutzen die Methode.
Die Einstellung gehört zum aktuell gebundenen Framebuffer. Für einen eigenen Framebuffer (FBO) sind nur gl.NONE und gl.COLOR_ATTACHMENTi erlaubt, wobei Eintrag i entweder gl.COLOR_ATTACHMENTi oder gl.NONE sein muss. Für den Standard-Framebuffer (null) ist genau ein Eintrag zulässig: gl.BACK oder gl.NONE.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $buffers Pflicht | Array<GLenum> | Liste der Zielpuffer. Erlaubt sind gl.NONE, gl.BACK (nur beim Standard-Framebuffer) und gl.COLOR_ATTACHMENT0 … gl.COLOR_ATTACHMENT15. Die Länge darf gl.MAX_DRAW_BUFFERS nicht überschreiten. |
Rückgabewert
undefined). Fehler werden über gl.getError() gemeldet.Beispiele
G-Buffer mit zwei Render Targets einrichten
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
const { width, height } = canvas;
const createTarget = () => {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
return tex;
};
const albedoTex = createTarget();
const normalTex = createTarget();
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, albedoTex, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, normalTex, 0);
// location 0 -> Attachment 0, location 1 -> Attachment 1
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
console.log(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE);
Passender Fragment-Shader (GLSL ES 3.00)
const fragmentSource = `#version 300 es
precision highp float;
in vec3 vNormal;
in vec2 vUv;
uniform sampler2D uDiffuse;
layout(location = 0) out vec4 outAlbedo;
layout(location = 1) out vec4 outNormal;
void main() {
outAlbedo = texture(uDiffuse, vUv);
outNormal = vec4(normalize(vNormal) * 0.5 + 0.5, 1.0);
}`;
const shader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shader, fragmentSource);
gl.compileShader(shader);
console.log(gl.getShaderParameter(shader, gl.COMPILE_STATUS));
Attachment vorübergehend deaktivieren und Limit prüfen
console.log('Max. Draw Buffers:', gl.getParameter(gl.MAX_DRAW_BUFFERS));
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
// Nur in Attachment 1 schreiben, Attachment 0 bleibt unverändert
gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]);
// Zurück zum Canvas: Standard-Framebuffer erlaubt nur BACK oder NONE
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.drawBuffers([gl.BACK]);
console.log(gl.getParameter(gl.DRAW_BUFFER0) === gl.BACK);
// Wichtig · Fallstricke
- Reihenfolge ist fest: Eintrag
imussgl.COLOR_ATTACHMENTiodergl.NONEsein.[gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT0]führt zuINVALID_OPERATION. - Beim Standard-Framebuffer ist nur ein Array mit genau einem Element (
gl.BACKodergl.NONE) erlaubt, sonstINVALID_OPERATION. - Mehr Einträge als
gl.MAX_DRAW_BUFFERSergebenINVALID_VALUE. WebGL 2 garantiert mindestens 4; verbreitet sind 8. - Die Einstellung wird pro Framebuffer gespeichert – nach dem Binden eines anderen FBO gilt dessen eigene Konfiguration.
gl.clear()betrifft alle aktiven Draw Buffers; für einzelne Puffer eignen sichclearBufferfv()und ähnliche Methoden.- In WebGL 1 steht die Funktionalität nur über die Erweiterung
WEBGL_draw_buffers(drawBuffersWEBGL()) zur Verfügung. WebGL 2 wird von allen aktuellen Browsern unterstützt, ältere Safari-Versionen (vor 15) jedoch nicht.