Signatur
Beschreibung
Mit createFramebuffer() legen Sie ein neues Framebuffer-Objekt (FBO) an. Ein Framebuffer ist ein Sammelbehälter für Anhänge (Attachments): Farbpuffer, Tiefenpuffer und Stencilpuffer. Statt direkt auf das sichtbare Canvas zu zeichnen, können Sie in einen eigenen Framebuffer rendern und das Ergebnis etwa als Textur weiterverwenden.
Typische Einsatzfälle sind Render-to-Texture für Nachbearbeitungseffekte (Weichzeichner, Bloom, Farbkorrektur), Shadow-Mapping, Picking (Objektauswahl über ID-Farben), Spiegelungen und GPGPU-Berechnungen. Das zurückgegebene Objekt ist zunächst leer. Sie binden es mit gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) und hängen danach mit gl.framebufferTexture2D() oder gl.framebufferRenderbuffer() Texturen bzw. Renderbuffer an.
Prüfen Sie nach dem Einrichten mit gl.checkFramebufferStatus(gl.FRAMEBUFFER), ob der Framebuffer vollständig ist (gl.FRAMEBUFFER_COMPLETE). Mit gl.bindFramebuffer(gl.FRAMEBUFFER, null) zeichnen Sie wieder auf das Canvas. Brauchen Sie den Framebuffer nicht mehr, geben Sie ihn mit gl.deleteFramebuffer() frei.
Rückgabewert
WebGLFramebuffer-Objekt ohne Anhänge. Ist der Kontext verloren (context lost), wird null zurückgegeben.Beispiele
Framebuffer mit Farbtextur für Render-to-Texture anlegen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const width = 512;
const height = 512;
// Zieltextur erzeugen
const targetTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, targetTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 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 erzeugen und Textur als Farbanhang festlegen
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, targetTexture, 0);
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(status === gl.FRAMEBUFFER_COMPLETE ? 'Framebuffer bereit' : `Unvollständig: 0x${status.toString(16)}`);
// In die Textur rendern
gl.viewport(0, 0, width, height);
gl.clearColor(0.2, 0.4, 0.8, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Zurück zum Canvas
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
Framebuffer mit Tiefenpuffer (Renderbuffer) für 3D-Szenen
const gl = document.querySelector('canvas').getContext('webgl');
const createRenderTarget = (w, h) => {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
const depth = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depth);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h);
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depth);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
throw new Error('Framebuffer unvollständig');
}
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
return { framebuffer, texture, depth };
};
const target = createRenderTarget(1024, 1024);
console.log(target.framebuffer instanceof WebGLFramebuffer);
Pixel aus einem Framebuffer lesen (Picking) und aufräumen
const gl = document.querySelector('canvas').getContext('webgl');
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
gl.viewport(0, 0, 4, 4);
gl.clearColor(1, 0, 0, 1); // Objekt-ID als Farbe (Rot = ID 255)
gl.clear(gl.COLOR_BUFFER_BIT);
const pixel = new Uint8Array(4);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(Array.from(pixel));
// Ressourcen freigeben
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteFramebuffer(fbo);
gl.deleteTexture(tex);
console.log(gl.isFramebuffer(fbo));