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

WebGLRenderingContext.bufferData()

Methode

Legt den Datenspeicher des aktuell an <code>target</code> gebundenen WebGL-Puffers an und füllt ihn optional mit Daten aus einem ArrayBuffer oder TypedArray.

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

Signatur

WebGLRenderingContext.prototype.bufferData(target, sizeOrData, usage)

Beschreibung

bufferData() reserviert GPU-Speicher für das Pufferobjekt, das gerade an den angegebenen Bindungspunkt (gl.ARRAY_BUFFER oder gl.ELEMENT_ARRAY_BUFFER) gebunden ist, und kopiert optional Daten hinein. Ein vorhandener Datenspeicher dieses Puffers wird dabei vollständig ersetzt, alte Inhalte gehen verloren.

Typischerweise lädt man damit Vertex-Daten (Positionen, Normalen, Texturkoordinaten, Farben) oder Indizes auf die GPU. Die Methode arbeitet immer auf dem Puffer, der vorher mit gl.bindBuffer() gebunden wurde, und nicht auf einem Pufferobjekt, das man ihr direkt übergibt.

Man kann entweder eine Größe in Bytes übergeben (der Speicher wird dann mit Nullen initialisiert) oder direkt ein ArrayBuffer, TypedArray bzw. eine DataView. Sollen die Daten später nur in Teilen aktualisiert werden, legt man den Speicher einmal mit bufferData() an und aktualisiert ihn danach mit bufferSubData(). Das ist meist schneller als jedes Mal neu zu allozieren.

Der Parameter usage ist ein Hinweis an den Treiber, wie oft die Daten geändert und gelesen werden. Er verändert nicht das Verhalten, kann aber die Leistung stark beeinflussen.

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Bindungspunkt: gl.ARRAY_BUFFER (Vertex-Attribute) oder gl.ELEMENT_ARRAY_BUFFER (Indizes). In WebGL 2 kommen weitere hinzu, z. B. gl.UNIFORM_BUFFER, gl.COPY_READ_BUFFER oder gl.PIXEL_PACK_BUFFER.
$sizeOrData Pflicht GLsizeiptr | ArrayBuffer | SharedArrayBuffer | TypedArray | DataView | null Entweder die Größe des Speichers in Bytes (Inhalt mit Nullen initialisiert) oder die Quelldaten, die in den Puffer kopiert werden. Bei null wird in WebGL 1 der Fehler INVALID_VALUE erzeugt.
$usage Pflicht GLenum Nutzungshinweis: gl.STATIC_DRAW (einmal setzen, oft zeichnen), gl.DYNAMIC_DRAW (häufig ändern, oft zeichnen), gl.STREAM_DRAW (einmal setzen, selten zeichnen). WebGL 2 ergänzt *_READ- und *_COPY-Varianten.
$srcOffset GLuint 0 Nur WebGL 2 mit TypedArray-Quelle: Startindex in Elementen (nicht in Bytes), ab dem gelesen wird.
$length GLuint 0 Nur WebGL 2: Anzahl der zu kopierenden Elemente. 0 bedeutet: bis zum Ende des Arrays.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler werden über gl.getError() gemeldet.

Beispiele

Dreieck-Positionen in einen Vertex-Puffer laden

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(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE));
24

Index-Puffer für ein Rechteck aus zwei Dreiecken

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

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);

// Später beim Zeichnen (Programm und Attribute vorausgesetzt):
// gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
console.log(gl.getError() === gl.NO_ERROR);
true

Speicher vorab reservieren und pro Frame teilweise aktualisieren

const gl = document.querySelector('canvas').getContext('webgl');
const MAX_PARTICLES = 1000;
const FLOATS_PER_PARTICLE = 2;

const particleBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
// Nur Größe in Bytes angeben -> Speicher wird mit Nullen gefüllt
gl.bufferData(
  gl.ARRAY_BUFFER,
  MAX_PARTICLES * FLOATS_PER_PARTICLE * Float32Array.BYTES_PER_ELEMENT,
  gl.DYNAMIC_DRAW
);

const data = new Float32Array(MAX_PARTICLES * FLOATS_PER_PARTICLE);

const update = (time) => {
  for (let i = 0; i < MAX_PARTICLES; i++) {
    data[i * 2] = Math.cos(time / 1000 + i) * 0.8;
    data[i * 2 + 1] = Math.sin(time / 1000 + i) * 0.8;
  }
  gl.bindBuffer(gl.ARRAY_BUFFER, particleBuffer);
  // Kein Neuanlegen, nur Inhalt überschreiben
  gl.bufferSubData(gl.ARRAY_BUFFER, 0, data);
  requestAnimationFrame(update);
};
requestAnimationFrame(update);

WebGL 2: nur einen Ausschnitt eines Arrays hochladen

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

const all = new Float32Array([9, 9, 1, 2, 3, 4, 9, 9]);
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
// Ab Element 2, genau 4 Elemente -> [1, 2, 3, 4]
gl.bufferData(gl.ARRAY_BUFFER, all, gl.STATIC_DRAW, 2, 4);

console.log(gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE));
16