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

WebGL2RenderingContext.bindBufferBase()

Methode

Bindet einen <code>WebGLBuffer</code> vollständig an einen indizierten Bindungspunkt (Uniform-Buffer oder Transform-Feedback) an der angegebenen Indexposition.

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

Signatur

WebGL2RenderingContext.prototype.bindBufferBase(target, index, buffer)

Beschreibung

bindBufferBase() ist das Gegenstück zu bindBuffer() für indizierte Bindungspunkte. WebGL 2 kennt zwei solche Ziele: gl.UNIFORM_BUFFER für Uniform Buffer Objects (UBOs) und gl.TRANSFORM_FEEDBACK_BUFFER für Transform-Feedback-Ausgaben. Jedes dieser Ziele hat mehrere nummerierte Slots. Mit bindBufferBase() legst du fest, welcher Buffer in welchem Slot liegt.

Der gesamte Buffer wird gebunden, also ab Offset 0 in voller Größe. Willst du nur einen Ausschnitt binden, etwa mehrere UBO-Blöcke in einem großen Buffer, nimm bindBufferRange(). Nebenbei bindet der Aufruf den Buffer auch an den allgemeinen (nicht indizierten) Bindungspunkt von target. Danach wirken also auch bufferData() oder bufferSubData() mit demselben target auf diesen Buffer.

Typischer Ablauf bei UBOs: Mit getUniformBlockIndex() den Block im Shader finden, mit uniformBlockBinding() dem Block einen Bindungspunkt-Index zuweisen und mit bindBufferBase() den Buffer an denselben Index binden. So können mehrere Shader-Programme dieselben Daten nutzen, zum Beispiel Kamera-Matrizen, ohne dass du pro Programm Uniforms setzen musst.

Parameter

Name Typ Default Beschreibung
$target Pflicht GLenum Indizierter Bindungspunkt: gl.UNIFORM_BUFFER oder gl.TRANSFORM_FEEDBACK_BUFFER.
$index Pflicht GLuint Index des Bindungspunkts. Muss kleiner sein als gl.MAX_UNIFORM_BUFFER_BINDINGS bzw. gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.
$buffer Pflicht WebGLBuffer | null Der zu bindende Buffer. Mit null wird die Bindung an diesem Index aufgehoben.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Fehler meldet die Methode über gl.getError().

Beispiele

Uniform Buffer Object für Kamera-Matrizen

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

const vsSource = `#version 300 es
layout(std140) uniform Camera {
  mat4 view;
  mat4 projection;
};
in vec4 aPosition;
void main() {
  gl_Position = projection * view * aPosition;
}`;
const fsSource = `#version 300 es
precision mediump float;
out vec4 color;
void main() { color = vec4(1.0); }`;

const compile = (type, src) => {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  return s;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);

// Bindungspunkt 0 für den Block "Camera"
const CAMERA_BINDING = 0;
const blockIndex = gl.getUniformBlockIndex(program, 'Camera');
gl.uniformBlockBinding(program, blockIndex, CAMERA_BINDING);

// UBO anlegen: 2 × mat4 = 32 floats = 128 Bytes
const ubo = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
gl.bufferData(gl.UNIFORM_BUFFER, 32 * 4, gl.DYNAMIC_DRAW);

// Buffer an Index 0 binden
gl.bindBufferBase(gl.UNIFORM_BUFFER, CAMERA_BINDING, ubo);

// Daten aktualisieren (Einheitsmatrizen)
const identity = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([...identity, ...identity]));
console.log(gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, CAMERA_BINDING) === ubo);
true

Transform Feedback: Vertex-Ausgaben in einen Buffer schreiben

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

const vs = `#version 300 es
in float aValue;
out float vDoubled;
void main() { vDoubled = aValue * 2.0; }`;
const fs = `#version 300 es
precision mediump float;
out vec4 c;
void main() { c = vec4(0.0); }`;

const sh = (t, s) => { const x = gl.createShader(t); gl.shaderSource(x, s); gl.compileShader(x); return x; };
const program = gl.createProgram();
gl.attachShader(program, sh(gl.VERTEX_SHADER, vs));
gl.attachShader(program, sh(gl.FRAGMENT_SHADER, fs));
// Varyings VOR dem Linken festlegen
gl.transformFeedbackVaryings(program, ['vDoubled'], gl.SEPARATE_ATTRIBS);
gl.linkProgram(program);
gl.useProgram(program);

const input = new Float32Array([1, 2, 3, 4]);
const inBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, inBuf);
gl.bufferData(gl.ARRAY_BUFFER, input, gl.STATIC_DRAW);
const loc = gl.getAttribLocation(program, 'aValue');
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 1, gl.FLOAT, false, 0, 0);

const outBuf = gl.createBuffer();
gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, outBuf);
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, input.byteLength, gl.STATIC_READ);
gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);

const tf = gl.createTransformFeedback();
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, outBuf);

gl.enable(gl.RASTERIZER_DISCARD);
gl.beginTransformFeedback(gl.POINTS);
gl.drawArrays(gl.POINTS, 0, input.length);
gl.endTransformFeedback();
gl.disable(gl.RASTERIZER_DISCARD);

// Bindung lösen, bevor der Buffer gelesen wird
gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);

const result = new Float32Array(input.length);
gl.bindBuffer(gl.COPY_READ_BUFFER, outBuf);
gl.getBufferSubData(gl.COPY_READ_BUFFER, 0, result);
console.log(Array.from(result));
[2, 4, 6, 8]

Bindung aufheben und Grenzen abfragen

const gl = document.createElement('canvas').getContext('webgl2');
const max = gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS);
console.log('Verfügbare UBO-Slots:', max);

const ubo = gl.createBuffer();
gl.bindBufferBase(gl.UNIFORM_BUFFER, 2, ubo);
gl.bindBufferBase(gl.UNIFORM_BUFFER, 2, null); // Slot 2 wieder freigeben
console.log(gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 2));
Verfügbare UBO-Slots: 24 null