Signatur
Beschreibung
Mit getUniformBlockIndex() fragst du ab, unter welchem Index ein im GLSL-ES-3.00-Shader deklarierter Uniform-Block (z. B. uniform Camera { ... };) innerhalb eines gelinkten Programms geführt wird. Dieser Index ist der erste Schritt, um einen Block mit einem Uniform Buffer Object (UBO) zu verbinden.
Der typische Ablauf sieht so aus: Index mit getUniformBlockIndex() ermitteln, den Block per uniformBlockBinding() einem Binding-Punkt zuordnen und anschließend einen Puffer mit bindBufferBase() oder bindBufferRange() an denselben Binding-Punkt hängen. So können mehrere Programme dieselben Daten (Kamera-Matrizen, Licht-Parameter) gemeinsam nutzen, ohne dass du jede Uniform einzeln setzen musst.
Der Name ist der Blockname aus der Deklaration, nicht der optionale Instanzname. Bei uniform Lights { ... } lights; lautet der korrekte Wert also "Lights". Die Methode funktioniert erst, nachdem linkProgram() erfolgreich ausgeführt wurde.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das erfolgreich gelinkte Programm, in dem der Uniform-Block gesucht wird. | |
| $uniformBlockName Pflicht | string | Der Blockname aus der GLSL-Deklaration (nicht der Instanzname), z. B. "Camera". |
Rückgabewert
gl.INVALID_INDEX (4294967295, also 0xFFFFFFFF) zurückgegeben.Beispiele
Uniform-Block-Index ermitteln und prüfen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
const vsSource = `#version 300 es
uniform Camera {
mat4 view;
mat4 projection;
};
in vec4 position;
void main() {
gl_Position = projection * view * position;
}`;
const fsSource = `#version 300 es
precision highp 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);
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(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);
const blockIndex = gl.getUniformBlockIndex(program, 'Camera');
if (blockIndex === gl.INVALID_INDEX) {
console.warn('Block "Camera" nicht gefunden');
} else {
console.log('Index von Camera:', blockIndex);
}
Block an ein Uniform Buffer Object binden
// Voraussetzung: gl und program aus dem vorherigen Beispiel
const BINDING_POINT = 0;
const blockIndex = gl.getUniformBlockIndex(program, 'Camera');
gl.uniformBlockBinding(program, blockIndex, BINDING_POINT);
// Benötigte Puffergröße direkt vom Treiber erfragen
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, BINDING_POINT, ubo);
// Zwei 4x4-Einheitsmatrizen (view + projection) hochladen
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('UBO-Größe in Bytes:', blockSize);
Blockname vs. Instanzname
// GLSL: uniform Lights { vec4 color; } lights;
const wrong = gl.getUniformBlockIndex(program, 'lights'); // Instanzname
const right = gl.getUniformBlockIndex(program, 'Lights'); // Blockname
console.log(wrong === gl.INVALID_INDEX); // true
console.log(right !== gl.INVALID_INDEX); // true, sofern der Block genutzt wird
// Wichtig · Fallstricke
- Nur WebGL 2: Die Methode gibt es nur auf
WebGL2RenderingContext, nicht auf einem WebGL-1-Kontext. Uniform-Blöcke setzen Shader mit#version 300 esvoraus. - Nicht mit -1 vergleichen: Bei einem Fehlschlag kommt
gl.INVALID_INDEX(0xFFFFFFFF) zurück, nicht-1wie beigetAttribLocation(). - Optimierte Blöcke: Wird ein Block im Shader nicht benutzt, kann der Compiler ihn entfernen. Dann liefert die Abfrage ebenfalls
INVALID_INDEX. - Speicherlayout: Nutze
layout(std140), damit die Offsets vorhersehbar sind. Beachte außerdem die Ausrichtung (vec3belegt 16 Bytes). Offsets beibindBufferRange()müssen ein Vielfaches vongl.UNIFORM_BUFFER_OFFSET_ALIGNMENTsein. - Rufe die Methode vor
linkProgram()oder nach einem fehlgeschlagenen Linken auf, entsteht der FehlerINVALID_OPERATION. - Unterstützt in allen aktuellen Browsern (Chrome, Edge, Firefox, Safari ab 15).