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

WebGL2RenderingContext.getUniformBlockIndex()

Methode

Liefert den Index eines benannten Uniform-Blocks (UBO) in einem gelinkten <code>WebGLProgram</code> oder <code>gl.INVALID_INDEX</code>, falls der Block nicht existiert.

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

Signatur

WebGL2RenderingContext.prototype.getUniformBlockIndex(program, uniformBlockName)

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

Typ
GLuint (number)
Beschreibung
Der Index des Uniform-Blocks. Gibt es keinen aktiven Block dieses Namens, wird 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);
}
Index von Camera: 0

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);
UBO-Größe in Bytes: 128

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
true true

// 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 es voraus.
  • Nicht mit -1 vergleichen: Bei einem Fehlschlag kommt gl.INVALID_INDEX (0xFFFFFFFF) zurück, nicht -1 wie bei getAttribLocation().
  • 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 (vec3 belegt 16 Bytes). Offsets bei bindBufferRange() müssen ein Vielfaches von gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT sein.
  • Rufe die Methode vor linkProgram() oder nach einem fehlgeschlagenen Linken auf, entsteht der Fehler INVALID_OPERATION.
  • Unterstützt in allen aktuellen Browsern (Chrome, Edge, Firefox, Safari ab 15).