Signatur
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
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);
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})`);
// Wichtig · Fallstricke
- Nur WebGL 2: Die Methode gibt es ausschließlich auf
WebGL2RenderingContext. Uniformblöcke setzen GLSL ES 3.00 voraus (#version 300 esin 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_BINDINGSerzeugtINVALID_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. werdenvec3auf 16 Byte aufgefüllt) und beibindBufferRange()aufUNIFORM_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.