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

WebGL2RenderingContext.bufferData()

Methode

Legt den Datenspeicher des aktuell an <code>target</code> gebundenen Pufferobjekts an und befüllt ihn optional mit Daten. Vorhandener Inhalt wird dabei verworfen.

seit JavaScript WebGL 2.0, Baseline: alle modernen Browser (seit 2 Kategorie: webapi

Signatur

WebGL2RenderingContext.prototype.bufferData(target, sizeOrSrcData, usage, srcOffset, length)

Beschreibung

bufferData() reserviert GPU-Speicher für das Pufferobjekt, das gerade mit bindBuffer() an das angegebene Ziel gebunden ist. Übergibt man eine Zahl, wird ein mit Nullen gefüllter Speicher dieser Größe (in Bytes) angelegt. Übergibt man ein ArrayBuffer, eine ArrayBufferView (z. B. Float32Array) oder ein SharedArrayBuffer, werden die Daten direkt in den Puffer kopiert.

Typische Einsatzfälle sind das Hochladen von Vertex-Positionen, Normalen und Texturkoordinaten (gl.ARRAY_BUFFER), von Indizes (gl.ELEMENT_ARRAY_BUFFER) und in WebGL 2 zusätzlich von Uniform-Blöcken (gl.UNIFORM_BUFFER), Transform-Feedback-Ausgaben oder Pixel-Pack-/Unpack-Puffern.

Neu gegenüber WebGL 1 ist die Überladung mit srcOffset und length: Damit lässt sich nur ein Ausschnitt einer ArrayBufferView hochladen, ohne vorher per subarray() eine neue Sicht anzulegen. Beide Angaben zählen in Elementen des Typed Arrays, nicht in Bytes.

Der Parameter usage ist ein Hinweis an den Treiber, wie oft die Daten geändert und gelesen werden. Er beeinflusst nur die Leistung, nicht das Verhalten. Sollen Daten später teilweise aktualisiert werden, legt man den Puffer einmal mit bufferData() an und nutzt danach bufferSubData(), das keinen neuen Speicher reserviert.

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Bindungsziel: gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER, gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER, gl.PIXEL_PACK_BUFFER oder gl.PIXEL_UNPACK_BUFFER.
$sizeOrSrcData Pflicht GLsizeiptr | ArrayBuffer | ArrayBufferView | SharedArrayBuffer | null Entweder die Größe des Speichers in Bytes (wird mit Nullen gefüllt) oder die Quelldaten, die in den Puffer kopiert werden. Bei null wird ein Puffer der Größe 0 angelegt.
$usage Pflicht GLenum Nutzungshinweis: gl.STATIC_DRAW, gl.DYNAMIC_DRAW, gl.STREAM_DRAW sowie in WebGL 2 zusätzlich gl.STATIC_READ, gl.DYNAMIC_READ, gl.STREAM_READ, gl.STATIC_COPY, gl.DYNAMIC_COPY, gl.STREAM_COPY.
$srcOffset GLuint 0 Nur mit ArrayBufferView: Index des ersten Elements, ab dem gelesen wird (in Elementen, nicht Bytes).
$length GLuint 0 Nur mit ArrayBufferView: Anzahl der zu kopierenden Elemente. 0 bedeutet: bis zum Ende der Sicht.

Rückgabewert

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

Beispiele

Vertex-Positionen eines Dreiecks hochladen

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

const positions = new Float32Array([
   0.0,  0.5,
  -0.5, -0.5,
   0.5, -0.5,
]);

const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
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('webgl2');

const vao = gl.createVertexArray();
gl.bindVertexArray(vao); // Index-Puffer-Bindung wird im VAO gespeichert

const indices = new Uint16Array([0, 1, 2, 2, 1, 3]);
const ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

// später: gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
console.log(gl.getError() === gl.NO_ERROR);
true

Uniform-Buffer vorab reservieren und pro Frame aktualisieren

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

// Platz für eine 4x4-Matrix (16 Floats = 64 Bytes)
const ubo = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
gl.bufferData(gl.UNIFORM_BUFFER, 64, gl.DYNAMIC_DRAW);
gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);

const matrix = new Float32Array(16);
const render = (time) => {
  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
  matrix[12] = Math.sin(time / 1000) * 0.5;
  gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
  gl.bufferSubData(gl.UNIFORM_BUFFER, 0, matrix); // kein Neuanlegen
  requestAnimationFrame(render);
};
requestAnimationFrame(render);

Nur einen Ausschnitt mit srcOffset und length hochladen

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

// Großes Array mit mehreren Meshes; Mesh B beginnt bei Element 6
const allVertices = new Float32Array([
  0, 0,  1, 0,  0, 1,        // Mesh A (6 Floats)
  0, 0,  1, 0,  1, 1,  0, 1  // Mesh B (8 Floats)
]);

const bufB = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufB);
gl.bufferData(gl.ARRAY_BUFFER, allVertices, gl.STATIC_DRAW, 6, 8);

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