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

WebGLRenderingContext.renderbufferStorage()

Methode

Legt den Datenspeicher des aktuell gebundenen Renderbuffers mit einem internen Format und einer Größe in Pixeln an und initialisiert ihn.

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

Signatur

WebGLRenderingContext.prototype.renderbufferStorage(target, internalFormat, width, height)

Beschreibung

renderbufferStorage() reserviert GPU-Speicher für das Renderbuffer-Objekt, das gerade mit gl.bindRenderbuffer(gl.RENDERBUFFER, rb) gebunden ist. Renderbuffer sind Bildpuffer, die man nicht als Textur ausliest. Sie eignen sich deshalb vor allem für Tiefen- und Stencil-Anhänge eines Framebuffers, also für Daten, die man beim Offscreen-Rendern braucht, aber nicht in einem Shader abtastet.

Typischer Einsatz: Man erzeugt einen Framebuffer, hängt eine Textur als Farb-Anhang an (COLOR_ATTACHMENT0) und einen Renderbuffer mit DEPTH_COMPONENT16 oder DEPTH_STENCIL als Tiefen-Anhang. So funktioniert der Tiefentest auch beim Rendern in eine Textur, z. B. bei Post-Processing, Picking oder Spiegelungen.

Ein erneuter Aufruf ersetzt den bisherigen Speicher komplett. Das nutzt man, wenn sich die Canvas-Größe ändert. Der Inhalt ist danach undefiniert (WebGL setzt ihn auf 0) und muss neu gerendert werden. Breite und Höhe dürfen gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) nicht überschreiten.

In WebGL 2 stehen deutlich mehr Formate zur Verfügung, z. B. RGBA8, DEPTH24_STENCIL8 oder DEPTH_COMPONENT32F. Für Multisampling gibt es dort die Variante renderbufferStorageMultisample().

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Muss gl.RENDERBUFFER sein.
$internalFormat Pflicht GLenum Internes Format des Speichers. In WebGL 1: gl.RGBA4, gl.RGB565, gl.RGB5_A1, gl.DEPTH_COMPONENT16, gl.STENCIL_INDEX8, gl.DEPTH_STENCIL. Mit Erweiterungen kommen weitere hinzu: EXT_sRGB liefert SRGB8_ALPHA8_EXT, WEBGL_color_buffer_float liefert RGBA32F_EXT. WebGL 2 ergänzt u. a. gl.RGBA8, gl.DEPTH24_STENCIL8, gl.DEPTH_COMPONENT24 und gl.DEPTH_COMPONENT32F.
$width Pflicht GLsizei (number) Breite in Pixeln, von 0 bis MAX_RENDERBUFFER_SIZE.
$height Pflicht GLsizei (number) Höhe in Pixeln, von 0 bis MAX_RENDERBUFFER_SIZE.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler meldet die Methode über gl.getError().

Beispiele

Tiefenpuffer für Render-to-Texture

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const width = 512, height = 512;

// Farb-Anhang als Textur
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
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);

// Tiefen-Anhang als Renderbuffer
const depthRb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);

const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRb);

const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
console.log(status === gl.FRAMEBUFFER_COMPLETE ? 'Framebuffer vollständig' : 'Fehler: ' + status);
Framebuffer vollständig

Renderbuffer bei Größenänderung neu anlegen

const gl = document.querySelector('canvas').getContext('webgl');
const depthRb = gl.createRenderbuffer();

const resize = () => {
  const w = gl.canvas.clientWidth * devicePixelRatio | 0;
  const h = gl.canvas.clientHeight * devicePixelRatio | 0;
  const max = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
  gl.canvas.width = Math.min(w, max);
  gl.canvas.height = Math.min(h, max);

  gl.bindRenderbuffer(gl.RENDERBUFFER, depthRb);
  // Ersetzt den alten Speicher vollständig
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, gl.canvas.width, gl.canvas.height);
  gl.bindRenderbuffer(gl.RENDERBUFFER, null);
  console.log('Renderbuffer:', gl.getRenderbufferParameter(gl.RENDERBUFFER === 0 ? 0 : gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH) ?? 'ungebunden');
};

window.addEventListener('resize', resize);
resize();

WebGL 2: Depth24/Stencil8 und Größe abfragen

const gl = document.createElement('canvas').getContext('webgl2');
const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, 1024, 768);

console.log(
  gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH),
  gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT),
  gl.getError() === gl.NO_ERROR
);
1024 768 true

// Wichtig · Fallstricke

  • Vor dem Aufruf muss ein Renderbuffer gebunden sein. Sonst erzeugt die Methode INVALID_OPERATION.
  • Ein ungültiges target oder internalFormat erzeugt INVALID_ENUM. Eine negative Größe oder ein Wert über MAX_RENDERBUFFER_SIZE erzeugt INVALID_VALUE. Ist nicht genug Speicher frei, erzeugt sie OUT_OF_MEMORY.
  • Alle Anhänge eines Framebuffers sollten dieselbe Größe haben. Sonst meldet checkFramebufferStatus() einen unvollständigen Framebuffer, z. B. FRAMEBUFFER_INCOMPLETE_DIMENSIONS in WebGL 1.
  • In WebGL 1 gilt: Den kombinierten Tiefen-/Stencil-Puffer DEPTH_STENCIL an DEPTH_STENCIL_ATTACHMENT anhängen, nicht getrennt an Tiefen- und Stencil-Anhang.
  • Einen Renderbuffer kann man im Shader nicht abtasten. Wenn man die Tiefe später auslesen will (z. B. für Shadow Mapping), braucht man eine Tiefentextur: in WebGL 2 nativ, in WebGL 1 über WEBGL_depth_texture.
  • Nach einer Größenänderung ist der Inhalt verloren und muss neu gerendert werden. Den Aufruf nicht in jedem Frame wiederholen, weil jede neue Zuweisung Leistung kostet.
  • Die Methode wird breit unterstützt, in allen modernen Browsern mit WebGL. Welche Formate verfügbar sind, hängt von der WebGL-Version und den aktivierten Erweiterungen ab.