Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.createFramebuffer()

WebGLRenderingContext.createFramebuffer()

Methode

Erstellt ein neues, leeres <code>WebGLFramebuffer</code>-Objekt, das als eigenes Renderziel (Offscreen-Rendering, Render-to-Texture) dient.

seit JavaScript WebGL 1.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.createFramebuffer()

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

Typ
WebGLFramebuffer | null
Beschreibung
Ein neues 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 bereit

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);
true

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));
[255, 0, 0, 255] false