Start · Sprachen · JavaScript · Referenz · WebGLRenderbuffer

WebGLRenderbuffer

Schnittstelle

Repräsentiert einen WebGL-Renderbuffer, also einen GPU-Speicherbereich für ein Bild, das als Renderziel (Farbe, Tiefe, Stencil) an einen Framebuffer gehängt wird.

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

Signatur

interface WebGLRenderbuffer extends WebGLObject

Beschreibung

Ein WebGLRenderbuffer ist ein undurchsichtiges Handle auf einen GPU-Speicherbereich, der ein einzelnes 2D-Bild enthält. Anders als eine WebGLTexture kann ein Renderbuffer nicht in Shadern gesampelt werden. Er dient ausschließlich als Anhang (Attachment) eines WebGLFramebuffer, typischerweise als Tiefen-, Stencil- oder Multisample-Farbpuffer beim Offscreen-Rendering.

Das Interface besitzt weder eigene Eigenschaften noch Methoden. Instanzen erzeugt man nicht mit new, sondern über gl.createRenderbuffer(). Bearbeitet wird der Puffer mit Methoden des Rendering-Kontexts: gl.bindRenderbuffer(), gl.renderbufferStorage() (bzw. in WebGL 2 gl.renderbufferStorageMultisample()), gl.framebufferRenderbuffer(), gl.getRenderbufferParameter(), gl.isRenderbuffer() und gl.deleteRenderbuffer().

Typische Einsatzfälle sind:

  • Tiefenpuffer für Render-to-Texture: Die Farbe landet in einer Textur, die Tiefe in einem Renderbuffer, weil man sie später nicht auslesen muss.
  • MSAA-Offscreen-Rendering (WebGL 2): Man rendert in einen Multisample-Renderbuffer und löst ihn mit gl.blitFramebuffer() in eine Textur auf.
  • Pixel-Auslesen mit gl.readPixels(), etwa für GPU-Picking.

Renderbuffer sind häufig etwas effizienter als Texturen, da der Treiber ein für das Rendern optimiertes internes Speicherformat wählen kann.

Rückgabewert

Typ
WebGLRenderbuffer
Beschreibung
Wird von WebGLRenderingContext.createRenderbuffer() bzw. WebGL2RenderingContext.createRenderbuffer() zurückgegeben. Das Objekt selbst hat keine öffentlichen Eigenschaften oder Methoden.

Beispiele

Renderbuffer erzeugen und als Tiefenpuffer anhängen

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');

// Renderbuffer anlegen (kein new!)
const depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 512, 512);

// Framebuffer mit Farbtextur + Tiefen-Renderbuffer
const colorTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTex);
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);

const fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);

const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(depthBuffer instanceof WebGLRenderbuffer);
console.log(status === gl.FRAMEBUFFER_COMPLETE);

gl.bindFramebuffer(gl.FRAMEBUFFER, null);
true true

Parameter eines Renderbuffers abfragen

const gl = document.createElement('canvas').getContext('webgl');
const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 256, 128);

const width  = gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH);
const height = gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT);
const format = gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT);

console.log(`${width}x${height}`, format === gl.RGBA4);
console.log(gl.isRenderbuffer(rb));
256x128 true true

MSAA-Rendering mit Multisample-Renderbuffer (WebGL 2)

const gl = document.createElement('canvas').getContext('webgl2');
const [w, h] = [800, 600];
const samples = Math.min(4, gl.getParameter(gl.MAX_SAMPLES));

// Multisample-Farbpuffer
const msaaColor = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, msaaColor);
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA8, w, h);

const msaaFbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, msaaFbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaColor);

gl.clearColor(0.2, 0.4, 0.8, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// ... hier Szene zeichnen ...

// Auflösen in den Standard-Framebuffer (Canvas)
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, msaaFbo);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);

// Aufräumen, wenn nicht mehr benötigt
gl.deleteFramebuffer(msaaFbo);
gl.deleteRenderbuffer(msaaColor);
console.log(gl.isRenderbuffer(msaaColor));
false

// Wichtig · Fallstricke

  • Kein Konstruktor: new WebGLRenderbuffer() wirft einen TypeError. Immer gl.createRenderbuffer() verwenden.
  • Nicht in Shadern lesbar: Wenn du das Ergebnis später als Textur samplen willst (z. B. Shadow Mapping), nimm eine WebGLTexture statt eines Renderbuffers.
  • Kontextgebunden: Ein Renderbuffer gehört genau zu dem Kontext, der ihn erzeugt hat. Nutzt man ihn in einem anderen Kontext, entsteht INVALID_OPERATION. Nach einem webglcontextlost-Ereignis werden alle Renderbuffer ungültig und müssen neu angelegt werden.
  • Formate: WebGL 1 unterstützt nur RGBA4, RGB565, RGB5_A1, DEPTH_COMPONENT16, STENCIL_INDEX8 und DEPTH_STENCIL. WebGL 2 bietet sized formats wie RGBA8, DEPTH24_STENCIL8 und Multisampling.
  • Größenlimit: Breite und Höhe dürfen gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) nicht überschreiten. Nach dem Anhängen immer mit gl.checkFramebufferStatus() prüfen.
  • Speicher: Die Garbage Collection gibt GPU-Speicher nicht zuverlässig frei. Nicht mehr benötigte Puffer deshalb explizit mit gl.deleteRenderbuffer() löschen, vor allem beim Ändern der Canvas-Größe.
  • Die Browser-Unterstützung ist umfassend (alle modernen Desktop- und Mobilbrowser). In Workern steht das Interface über OffscreenCanvas zur Verfügung.