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

WebGL2RenderingContext.bindBufferRange()

Methode

Bindet einen Teilbereich (<code>offset</code> + <code>size</code>) eines <code>WebGLBuffer</code> an einen indizierten Bindungspunkt für Uniform-Blöcke oder Transform Feedback.

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

Signatur

WebGL2RenderingContext.prototype.bindBufferRange(target, index, buffer, offset, size)

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

Typ
void
Beschreibung
Kein 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);
Ausrichtung: 256 true

// Wichtig · Fallstricke

  • Ausrichtung: offset muss bei UBOs ein Vielfaches von UNIFORM_BUFFER_OFFSET_ALIGNMENT sein (häufig 256 Byte). Sonst gibt es INVALID_VALUE. Plane den Abstand zwischen den Blöcken (Stride) entsprechend.
  • Größe: Wenn size kleiner ist als der Wert von UNIFORM_BLOCK_DATA_SIZE des Shader-Blocks, schlägt der nächste Draw-Call mit INVALID_OPERATION fehl. Übersteigt offset + size die Puffergröße, schlägt der Draw-Call ebenfalls fehl.
  • Nutze im Shader layout(std140), damit die Byte-Anordnung vorhersehbar ist (z. B. wird ein vec3 auf 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.