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

WebGL2RenderingContext.uniformBlockBinding()

Methode

Verknüpft einen aktiven Uniformblock eines Shader-Programms mit einem Uniform-Buffer-Binding-Punkt, an den später ein Uniform Buffer Object gebunden wird.

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

Signatur

WebGL2RenderingContext.prototype.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding)

Beschreibung

Mit uniformBlockBinding() legst du fest, aus welchem Binding-Punkt ein Uniformblock (in GLSL ES 3.00 als uniform Name { ... }; deklariert) seine Daten liest. Die eigentlichen Daten liegen in einem Uniform Buffer Object (UBO), das du mit bindBufferBase() oder bindBufferRange() und dem Ziel gl.UNIFORM_BUFFER an denselben Binding-Punkt bindest. Der Binding-Punkt ist also das Bindeglied zwischen Shader-Block und Buffer.

Der typische Ablauf sieht so aus: Zuerst ermittelst du mit getUniformBlockIndex() den Index des Blocks im gelinkten Programm, weist ihm dann mit uniformBlockBinding() einen Binding-Punkt zu und bindest schließlich den Buffer an diesen Punkt. Weil die Zuweisung im Programmobjekt gespeichert wird, reicht es in der Regel, sie einmal nach dem Linken zu setzen.

Besonders nützlich ist das, wenn mehrere Programme dieselben Daten teilen – etwa Kamera-Matrizen oder Lichtparameter. Weist du in allen Programmen dem Block Camera denselben Binding-Punkt zu, musst du den Buffer nur einmal pro Frame aktualisieren, statt in jedem Programm einzelne uniform*()-Aufrufe abzusetzen.

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram Das erfolgreich gelinkte Shader-Programm, das den Uniformblock enthält.
$uniformBlockIndex Pflicht GLuint (number) Index des aktiven Uniformblocks, üblicherweise ermittelt über gl.getUniformBlockIndex(program, name).
$uniformBlockBinding Pflicht GLuint (number) Der Binding-Punkt, dem der Block zugewiesen wird. Muss kleiner als gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS) sein.

Rückgabewert

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

Beispiele

Uniformblock mit einem UBO verbinden

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

const vsSource = `#version 300 es
uniform Camera {
  mat4 view;
  mat4 projection;
};
in vec4 aPosition;
void main() {
  gl_Position = projection * view * aPosition;
}`;

const fsSource = `#version 300 es
precision highp float;
out vec4 outColor;
void main() { outColor = vec4(1.0, 0.5, 0.0, 1.0); }`;

const compile = (type, src) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, src);
  gl.compileShader(shader);
  return shader;
};

const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);

// 1. Blockindex ermitteln
const blockIndex = gl.getUniformBlockIndex(program, 'Camera');

// 2. Block dem Binding-Punkt 0 zuweisen
const CAMERA_BINDING = 0;
gl.uniformBlockBinding(program, blockIndex, CAMERA_BINDING);

// 3. UBO anlegen und an denselben Binding-Punkt binden
const blockSize = gl.getActiveUniformBlockParameter(
  program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE
);
const ubo = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
gl.bufferData(gl.UNIFORM_BUFFER, blockSize, gl.DYNAMIC_DRAW);
gl.bindBufferBase(gl.UNIFORM_BUFFER, CAMERA_BINDING, ubo);

console.log('Blockgröße:', blockSize);
Blockgröße: 128

Gemeinsamen Kamera-Block für mehrere Programme nutzen

const CAMERA_BINDING = 0;

// programs: Array bereits gelinkter WebGLProgram-Objekte
const setupCameraBlock = (gl, programs) => {
  for (const program of programs) {
    const index = gl.getUniformBlockIndex(program, 'Camera');
    if (index === gl.INVALID_INDEX) continue; // Block nicht vorhanden/aktiv
    gl.uniformBlockBinding(program, index, CAMERA_BINDING);
  }
};

// Einmal pro Frame aktualisieren – gilt für alle Programme
const updateCamera = (gl, ubo, view, projection) => {
  gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
  gl.bufferSubData(gl.UNIFORM_BUFFER, 0, view);        // Float32Array(16)
  gl.bufferSubData(gl.UNIFORM_BUFFER, 64, projection); // Float32Array(16)
  gl.bindBuffer(gl.UNIFORM_BUFFER, null);
};

Zuweisung prüfen und Grenzen abfragen

const maxBindings = gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS);
const index = gl.getUniformBlockIndex(program, 'Camera');

gl.uniformBlockBinding(program, index, 2);

const binding = gl.getActiveUniformBlockParameter(
  program, index, gl.UNIFORM_BLOCK_BINDING
);
console.log(`Binding: ${binding} (max. ${maxBindings - 1})`);
Binding: 2 (max. 71)

// Wichtig · Fallstricke

  • Nur WebGL 2: Die Methode gibt es ausschließlich auf WebGL2RenderingContext. Uniformblöcke setzen GLSL ES 3.00 voraus (#version 300 es in der ersten Zeile).
  • Programm muss gelinkt sein: Rufe die Methode erst nach linkProgram() auf. Beim erneuten Linken werden die Zuweisungen auf 0 zurückgesetzt und müssen neu gesetzt werden.
  • INVALID_INDEX: Ist der Block im Shader nicht vorhanden oder wurde er vom Compiler wegoptimiert, liefert getUniformBlockIndex() gl.INVALID_INDEX. Ein Aufruf mit diesem Index oder mit einem Binding-Punkt ≥ MAX_UNIFORM_BUFFER_BINDINGS erzeugt INVALID_VALUE.
  • Standardwert 0: Ohne Zuweisung liegen alle Blöcke auf Binding-Punkt 0 – bei mehreren Blöcken lesen sie dann ungewollt aus demselben Buffer.
  • Speicherlayout: WebGL 2 nutzt standardmäßig std140. Achte auf Ausrichtung (z. B. werden vec3 auf 16 Byte aufgefüllt) und bei bindBufferRange() auf UNIFORM_BUFFER_OFFSET_ALIGNMENT.
  • Explizite layout(binding = N)-Qualifier gibt es in GLSL ES 3.00 nicht; die Zuweisung muss daher immer über diese Methode erfolgen.