Start · Sprachen · JavaScript · Referenz · WebGLBuffer

WebGLBuffer

Schnittstelle

<code>WebGLBuffer</code> ist ein undurchsichtiges Handle auf einen GPU-Puffer, der Vertex-Daten (Positionen, Farben, Normalen, Texturkoordinaten) oder Indizes speichert.

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

Signatur

interface WebGLBuffer extends WebGLObject

Beschreibung

Ein WebGLBuffer steht für einen Speicherbereich auf der Grafikkarte. Man greift nie direkt auf den Inhalt zu, sondern arbeitet nur über den WebGL-Kontext damit: gl.createBuffer() erzeugt das Objekt, gl.bindBuffer() bindet es an ein Ziel (z. B. gl.ARRAY_BUFFER oder gl.ELEMENT_ARRAY_BUFFER) und gl.bufferData() bzw. gl.bufferSubData() lädt die Daten hoch.

Die Schnittstelle hat keine eigenen Eigenschaften oder Methoden und keinen öffentlichen Konstruktor. Man bekommt Instanzen nur über WebGLRenderingContext.createBuffer() oder WebGL2RenderingContext.createBuffer(). Das Objekt dient als Kennung, die man an andere WebGL-Funktionen übergibt.

Typischer Ablauf: Puffer anlegen, binden, mit einem typisierten Array (Float32Array, Uint16Array …) füllen und dann per gl.vertexAttribPointer() mit einem Attribut im Shader verknüpfen. Mit dem Nutzungshinweis (gl.STATIC_DRAW, gl.DYNAMIC_DRAW, gl.STREAM_DRAW) teilt man dem Treiber mit, wie oft sich die Daten ändern werden.

Braucht man den Puffer nicht mehr, gibt gl.deleteBuffer() den GPU-Speicher frei. Ob ein Wert ein gültiger Puffer ist, prüft man mit gl.isBuffer().

Rückgabewert

Typ
WebGLBuffer
Beschreibung
Kein Konstruktor. Instanzen liefert nur gl.createBuffer(), im Fehlerfall (z. B. nach Kontextverlust) kommt null zurück.

Beispiele

Puffer erzeugen und mit Vertex-Positionen füllen

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

// Dreieck: drei Punkte mit je x, y
const positions = new Float32Array([
   0.0,  0.5,
  -0.5, -0.5,
   0.5, -0.5
]);

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

console.log(positionBuffer instanceof WebGLBuffer);
console.log(gl.isBuffer(positionBuffer));
true true

Puffer mit einem Shader-Attribut verknüpfen und zeichnen

// Vorausgesetzt: 'program' ist ein gelinktes WebGLProgram mit 'attribute vec2 a_position;'
const loc = gl.getAttribLocation(program, 'a_position');

gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.enableVertexAttribArray(loc);
// 2 Komponenten pro Vertex, Float, nicht normalisiert, dicht gepackt
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);

gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);

Index-Puffer für ein Rechteck aus zwei Dreiecken

const indices = new Uint16Array([0, 1, 2, 2, 1, 3]);

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

// Beim Zeichnen die Indizes verwenden
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

Dynamische Daten aktualisieren und Puffer freigeben

const particleBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
// Speicher für 1000 Partikel (x, y) reservieren
gl.bufferData(gl.ARRAY_BUFFER, 1000 * 2 * 4, gl.DYNAMIC_DRAW);

const update = (data) => {
  gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
  gl.bufferSubData(gl.ARRAY_BUFFER, 0, data); // ab Byte-Offset 0
};

update(new Float32Array([0.1, 0.2, 0.3, 0.4]));

// Aufräumen
gl.deleteBuffer(particleBuffer);
console.log(gl.isBuffer(particleBuffer));
false

// Wichtig · Fallstricke

  • Kein Konstruktor: new WebGLBuffer() wirft einen TypeError. Puffer immer mit gl.createBuffer() anlegen.
  • An einen Kontext gebunden: Ein Puffer gehört zu genau dem Kontext, der ihn erzeugt hat. In einem anderen Kontext führt er zu INVALID_OPERATION.
  • Ziel steht nach dem ersten Binden fest: Wer einen Puffer einmal an ELEMENT_ARRAY_BUFFER gebunden hat, darf ihn in WebGL nicht mehr an ARRAY_BUFFER binden (und umgekehrt).
  • Kontextverlust: Nach dem Ereignis webglcontextlost sind alle Puffer ungültig. Sie müssen nach webglcontextrestored neu erzeugt und befüllt werden.
  • Speicher wird nicht automatisch freigegeben: Die Garbage Collection räumt GPU-Speicher nicht zuverlässig oder rechtzeitig auf. Nicht mehr gebrauchte Puffer daher ausdrücklich mit gl.deleteBuffer() löschen.
  • Performance: bufferData reserviert jedes Mal neuen Speicher. Für häufige Änderungen besser einmal reservieren und danach mit bufferSubData aktualisieren.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt (WebGL 1 und 2). WebGL 2 ergänzt weitere Ziele wie UNIFORM_BUFFER, COPY_READ_BUFFER und TRANSFORM_FEEDBACK_BUFFER. Außerdem ist es in Workern über OffscreenCanvas verfügbar.