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

WebGLRenderingContext.createBuffer()

Methode

Erstellt ein neues, leeres <code>WebGLBuffer</code>-Objekt, in dem Vertex-Daten wie Positionen, Farben, Normalen oder Indizes auf der GPU gespeichert werden.

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

Signatur

WebGLRenderingContext.prototype.createBuffer()

Beschreibung

createBuffer() legt ein neues Buffer-Objekt auf der GPU an und gibt ein WebGLBuffer zurück, mit dem du auf dieses Objekt zugreifst. Der Buffer ist zunächst leer und hat noch keinen Typ. Erst mit gl.bindBuffer() wird er an ein Ziel gebunden, etwa gl.ARRAY_BUFFER für Vertex-Attribute oder gl.ELEMENT_ARRAY_BUFFER für Indizes. Danach überträgst du die Daten mit gl.bufferData().

Der typische Ablauf sieht so aus: anlegen → binden → befüllen → mit einem Attribut verknüpfen. Die Verknüpfung erledigen gl.vertexAttribPointer() und gl.enableVertexAttribArray(). Jede Geometrie, die du mit gl.drawArrays() oder gl.drawElements() zeichnest, braucht mindestens einen solchen Buffer.

Ein Buffer bleibt an das Ziel gebunden, an das er zuerst gebunden wurde. Ein ELEMENT_ARRAY_BUFFER lässt sich also später nicht als ARRAY_BUFFER verwenden. Brauchst du den Buffer nicht mehr, gibst du den GPU-Speicher mit gl.deleteBuffer() frei. So entstehen keine Speicherlecks, besonders bei Szenen, die sich häufig ändern.

Die Methode gibt es auch auf WebGL2RenderingContext. Dort kommen weitere Bindungsziele hinzu, zum Beispiel gl.UNIFORM_BUFFER, gl.COPY_READ_BUFFER und gl.TRANSFORM_FEEDBACK_BUFFER.

Rückgabewert

Typ
WebGLBuffer | null
Beschreibung
Ein neues WebGLBuffer-Objekt. Ist der Kontext verloren gegangen (context lost), wird null zurückgegeben.

Beispiele

Dreieck: Positions-Buffer anlegen und befüllen

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

// Drei Eckpunkte (x, y) in Clip-Koordinaten
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.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE));
true 24

Buffer mit einem Shader-Attribut verknüpfen und zeichnen

// Annahme: 'program' ist ein gelinktes Shader-Programm
// mit dem Attribut 'a_position' (vec2)
const drawTriangle = (gl, program, buffer) => {
  const loc = gl.getAttribLocation(program, 'a_position');
  gl.useProgram(program);
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(loc);
  // 2 Komponenten pro Vertex, Float, nicht normalisiert, dicht gepackt
  gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
};

drawTriangle(gl, program, positionBuffer);

Index-Buffer für ein Rechteck mit drawElements

const vertices = new Float32Array([
  -0.5,  0.5,   // 0 oben links
  -0.5, -0.5,   // 1 unten links
   0.5, -0.5,   // 2 unten rechts
   0.5,  0.5,   // 3 oben rechts
]);
const indices = new Uint16Array([0, 1, 2, 0, 2, 3]);

const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

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

// ... Attribut wie oben einrichten, dann:
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);

Aufräumen und Umgang mit Kontextverlust

const buffer = gl.createBuffer();
if (!buffer) {
  console.warn('WebGL-Kontext verloren – Buffer konnte nicht erstellt werden.');
}

// Wenn der Buffer nicht mehr gebraucht wird:
gl.deleteBuffer(buffer);
console.log(gl.isBuffer(buffer));

canvas.addEventListener('webglcontextrestored', () => {
  // Alle Buffer müssen neu erstellt und befüllt werden
  initBuffers(gl);
});
false

// Wichtig · Fallstricke

  • Kontextverlust: Verliert der Browser den Kontext (Event webglcontextlost), werden alle Buffer ungültig und createBuffer() gibt null zurück. Nach webglcontextrestored musst du alle Buffer neu anlegen und befüllen.
  • Zielbindung ist endgültig: Ein Buffer, der einmal an ELEMENT_ARRAY_BUFFER gebunden war, lässt sich nicht an ARRAY_BUFFER binden, und umgekehrt. Ein Versuch erzeugt INVALID_OPERATION.
  • Leerer Buffer: createBuffer() reserviert noch keinen Datenspeicher. Ohne bufferData() hat der Buffer die Größe 0, und Zeichenaufrufe schlagen fehl oder zeichnen nichts.
  • Performance: Lege Buffer möglichst einmal an und verwende sie wieder. Für Daten, die sich oft ändern, nimmst du gl.DYNAMIC_DRAW zusammen mit bufferSubData(), statt in jedem Frame neue Buffer zu erzeugen.
  • Indextypen in WebGL 1: Uint32Array-Indizes funktionieren nur mit der Erweiterung OES_element_index_uint. In WebGL 2 sind sie immer verfügbar.
  • Speicher freigeben: Gib nicht mehr benötigte Buffer mit deleteBuffer() frei. Auf die Garbage Collection solltest du dich beim GPU-Speicher nicht verlassen.
  • Alle modernen Browser unterstützen die Methode, auch in OffscreenCanvas und Web Workers.