Signatur
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
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));
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));
// Wichtig · Fallstricke
- Kein Konstruktor:
new WebGLBuffer()wirft einenTypeError. Puffer immer mitgl.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_BUFFERgebunden hat, darf ihn in WebGL nicht mehr anARRAY_BUFFERbinden (und umgekehrt). - Kontextverlust: Nach dem Ereignis
webglcontextlostsind alle Puffer ungültig. Sie müssen nachwebglcontextrestoredneu 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:
bufferDatareserviert jedes Mal neuen Speicher. Für häufige Änderungen besser einmal reservieren und danach mitbufferSubDataaktualisieren. - Kompatibilität: Wird von allen modernen Browsern unterstützt (WebGL 1 und 2). WebGL 2 ergänzt weitere Ziele wie
UNIFORM_BUFFER,COPY_READ_BUFFERundTRANSFORM_FEEDBACK_BUFFER. Außerdem ist es in Workern überOffscreenCanvasverfügbar.