Signatur
Beschreibung
bindFramebuffer() legt fest, welcher Framebuffer als aktuelles Ziel für Zeichen- und Lesebefehle dient. Standardmäßig rendert WebGL in den Standard-Framebuffer, also in das <canvas>. Bindest du ein eigenes WebGLFramebuffer-Objekt, gehen alle folgenden Aufrufe wie drawArrays(), drawElements(), clear() und readPixels() an dessen Anhänge (Texturen oder Renderbuffer).
Gebraucht wird das vor allem für Render-to-Texture: Nachbearbeitungseffekte wie Weichzeichnen oder Bloom, Schattenkarten, Picking (Objektauswahl über Farb-IDs), Spiegelungen oder GPGPU-Berechnungen. Übergibst du null, bindet WebGL wieder den Standard-Framebuffer, und es wird erneut auf das Canvas gezeichnet.
In WebGL 1 gibt es nur das Ziel gl.FRAMEBUFFER. In WebGL 2 (WebGL2RenderingContext) kommen gl.DRAW_FRAMEBUFFER und gl.READ_FRAMEBUFFER hinzu. Damit lassen sich Lese- und Schreibziel getrennt binden, etwa für blitFramebuffer(). gl.FRAMEBUFFER bindet dort beide Ziele gleichzeitig.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Das Bindungsziel. In WebGL 1 nur gl.FRAMEBUFFER. In WebGL 2 zusätzlich gl.DRAW_FRAMEBUFFER (Ziel für Zeichnen und Löschen) und gl.READ_FRAMEBUFFER (Quelle für readPixels, copyTexImage2D und blitFramebuffer). |
|
| $framebuffer Pflicht | WebGLFramebuffer | null | Das zu bindende Framebuffer-Objekt, erzeugt mit gl.createFramebuffer(). Mit null wird wieder der Standard-Framebuffer (das Canvas) gebunden. |
Rückgabewert
undefined). Fehler meldet WebGL über gl.getError().Beispiele
Framebuffer mit Textur-Anhang anlegen (Render-to-Texture)
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
// Zieltextur anlegen
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 512, 512, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// Framebuffer anlegen und binden
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(status === gl.FRAMEBUFFER_COMPLETE ? 'Framebuffer bereit' : `Fehler: ${status}`);
// Wieder auf das Canvas umschalten
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
Zeichenschleife: erst in die Textur, dann auf das Canvas
const renderFrame = (gl, fbo, drawScene, drawPostProcess) => {
// Durchlauf 1: Szene in den Offscreen-Framebuffer zeichnen
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.viewport(0, 0, 512, 512);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
drawScene();
// Durchlauf 2: Ergebnis als Textur auf das Canvas bringen
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
drawPostProcess();
};
Picking: ein Pixel aus dem Framebuffer auslesen
const pickAt = (gl, fbo, x, y) => {
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
const pixel = new Uint8Array(4);
// WebGL-Koordinaten beginnen unten links
gl.readPixels(x, 512 - y - 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// Objekt-ID aus dem Rot- und Grünkanal zusammensetzen
return pixel[0] + (pixel[1] << 8);
};
console.log(pickAt(gl, fbo, 100, 200));
WebGL 2: Multisample-Framebuffer per Blit auflösen
const gl2 = document.querySelector('canvas').getContext('webgl2');
// msaaFbo und resolveFbo seien vorher angelegt
gl2.bindFramebuffer(gl2.READ_FRAMEBUFFER, msaaFbo);
gl2.bindFramebuffer(gl2.DRAW_FRAMEBUFFER, resolveFbo);
gl2.blitFramebuffer(0, 0, 512, 512, 0, 0, 512, 512, gl2.COLOR_BUFFER_BIT, gl2.NEAREST);
gl2.bindFramebuffer(gl2.FRAMEBUFFER, null);
// Wichtig · Fallstricke
- Viewport wird nicht automatisch angepasst: Nach dem Umschalten musst du
gl.viewport()selbst auf die Größe des Framebuffers bzw. des Canvas setzen. Sonst erscheint das Bild abgeschnitten oder verzerrt. - Vollständigkeit prüfen: Vor dem Zeichnen sollte
gl.checkFramebufferStatus()den WertFRAMEBUFFER_COMPLETEliefern. Andernfalls schlagen Zeichenbefehle mitINVALID_FRAMEBUFFER_OPERATIONfehl. - Feedback-Schleife: Eine Textur darf nicht gleichzeitig am gebundenen Framebuffer hängen und im Shader gelesen werden. Das ist undefiniertes Verhalten bzw. ein
INVALID_OPERATION-Fehler. - Ein ungültiges
targeterzeugtINVALID_ENUM. Ein bereits mitdeleteFramebuffer()gelöschtes Objekt erzeugtINVALID_OPERATION.DRAW_FRAMEBUFFERundREAD_FRAMEBUFFERgibt es nur in WebGL 2. - Häufiges Umschalten des Framebuffers ist auf mobilen GPUs (Tile-basiertes Rendern) teuer. Fasse Zeichendurchläufe deshalb möglichst zusammen.
- Die Methode steht in allen modernen Browsern zur Verfügung, auch in
OffscreenCanvas-Kontexten innerhalb von Web Workern.