Signatur
Beschreibung
bindBufferRange() verknüpft einen Ausschnitt eines Puffers mit einem indizierten Bindungspunkt. Zulässige Ziele sind gl.UNIFORM_BUFFER (Uniform Buffer Objects, UBOs) und gl.TRANSFORM_FEEDBACK_BUFFER. Anders als bindBufferBase(), das immer den ganzen Puffer bindet, gibt man hier Startversatz und Länge in Bytes an.
Typischer Einsatzfall: Man legt einen großen UBO an, in dem die Uniform-Daten mehrerer Objekte oder Materialien hintereinander liegen, und bindet vor jedem Draw-Call nur den passenden Abschnitt an denselben Bindungspunkt. Das spart Puffer-Objekte und bufferSubData()-Aufrufe pro Frame.
Nebeneffekt: Wie bindBufferBase() bindet der Aufruf den Puffer zusätzlich an den allgemeinen Bindungspunkt target, als hätte man gl.bindBuffer(target, buffer) aufgerufen. Der Shader-Uniform-Block wird über gl.uniformBlockBinding() mit demselben index verbunden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | GLenum | Bindungspunkt: gl.UNIFORM_BUFFER oder gl.TRANSFORM_FEEDBACK_BUFFER. |
|
| $index Pflicht | GLuint | Index des Bindungspunkts. Muss kleiner als gl.MAX_UNIFORM_BUFFER_BINDINGS bzw. gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS sein. |
|
| $buffer Pflicht | WebGLBuffer | null | Der zu bindende Puffer. null löst die Bindung an diesem Index. |
|
| $offset Pflicht | GLintptr (number) | Startversatz in Bytes. Bei UNIFORM_BUFFER ein Vielfaches von gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT, bei Transform Feedback ein Vielfaches von 4. |
|
| $size Pflicht | GLsizeiptr (number) | Länge des Bereichs in Bytes; muss größer als 0 sein (bei Transform Feedback ein Vielfaches von 4). |
Rückgabewert
undefined). Fehler werden über gl.getError() gemeldet.Beispiele
Mehrere Objekte aus einem großen UBO zeichnen
const gl = document.querySelector('canvas').getContext('webgl2');
// Shader: layout(std140) uniform ObjectData { mat4 model; vec4 color; };
const blockIndex = gl.getUniformBlockIndex(program, 'ObjectData');
const BINDING = 0;
gl.uniformBlockBinding(program, blockIndex, BINDING);
// Blockgröße (80 Byte) auf die geforderte Ausrichtung aufrunden
const align = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
const blockSize = 80;
const stride = Math.ceil(blockSize / align) * align;
const objectCount = 3;
const data = new Float32Array((stride * objectCount) / 4);
// ... data für jedes Objekt ab (i * stride / 4) befüllen ...
const ubo = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
gl.bufferData(gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW);
gl.useProgram(program);
for (let i = 0; i < objectCount; i++) {
gl.bindBufferRange(gl.UNIFORM_BUFFER, BINDING, ubo, i * stride, blockSize);
gl.drawArrays(gl.TRIANGLES, 0, 36);
}
Transform Feedback in einen Pufferabschnitt schreiben
const tfBuffer = gl.createBuffer();
gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4096, gl.DYNAMIC_COPY);
const tf = gl.createTransformFeedback();
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
// Nur die zweite Hälfte des Puffers beschreiben
gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer, 2048, 2048);
gl.enable(gl.RASTERIZER_DISCARD);
gl.beginTransformFeedback(gl.POINTS);
gl.drawArrays(gl.POINTS, 0, 100);
gl.endTransformFeedback();
gl.disable(gl.RASTERIZER_DISCARD);
// Bindung wieder lösen
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
Ausrichtung prüfen und Fehler erkennen
const align = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
console.log('Ausrichtung:', align);
gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, ubo, 10, 64); // 10 ist nicht ausgerichtet
console.log(gl.getError() === gl.INVALID_VALUE);
// Wichtig · Fallstricke
- Ausrichtung:
offsetmuss bei UBOs ein Vielfaches vonUNIFORM_BUFFER_OFFSET_ALIGNMENTsein (häufig 256 Byte). Sonst gibt esINVALID_VALUE. Plane den Abstand zwischen den Blöcken (Stride) entsprechend. - Größe: Wenn
sizekleiner ist als der Wert vonUNIFORM_BLOCK_DATA_SIZEdes Shader-Blocks, schlägt der nächste Draw-Call mitINVALID_OPERATIONfehl. Übersteigtoffset + sizedie Puffergröße, schlägt der Draw-Call ebenfalls fehl. - Nutze im Shader
layout(std140), damit die Byte-Anordnung vorhersehbar ist (z. B. wird einvec3auf 16 Byte aufgefüllt). - WebGL verbietet, denselben Puffer gleichzeitig für Transform Feedback und für andere Bindungen zu nutzen (
INVALID_OPERATION). - Nur in WebGL 2 verfügbar, also nicht in
WebGLRenderingContext(WebGL 1). Wird von allen aktuellen Browsern unterstützt, auch von Safari ab Version 15.