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

WebGL2RenderingContext.getActiveUniformBlockName()

Methode

Gibt den Namen des aktiven Uniform-Blocks an einem bestimmten Index innerhalb eines gelinkten <code>WebGLProgram</code> zurück.

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

Signatur

WebGL2RenderingContext.prototype.getActiveUniformBlockName(program, uniformBlockIndex)

Beschreibung

getActiveUniformBlockName() gibt den im GLSL-Shader deklarierten Namen eines Uniform-Blocks (Uniform Buffer Object, UBO) zurück. Uniform-Blöcke gibt es erst ab WebGL 2 (GLSL ES 3.00, #version 300 es). Mit ihnen fasst man mehrere Uniforms, etwa Kamera-Matrizen oder Lichtparameter, in einem Puffer zusammen, den sich mehrere Programme teilen können.

Man braucht die Methode vor allem zur Introspektion: Man fragt über getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS) die Anzahl der aktiven Blöcke ab, durchläuft die Indizes von 0 bis Anzahl - 1 und liest für jeden Index den Namen aus. So kann eine Engine Blöcke automatisch den passenden Binding-Points zuordnen, ohne die Namen fest im Code zu hinterlegen.

Der Weg geht auch umgekehrt: Kennt man den Namen schon, liefert getUniformBlockIndex() den Index dazu. Weitere Eigenschaften eines Blocks (Datengröße, Anzahl der Uniforms, Binding) liest man mit getActiveUniformBlockParameter() aus.

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram Das erfolgreich gelinkte Programm, dessen Uniform-Blöcke abgefragt werden.
$uniformBlockIndex Pflicht GLuint (number) Index des aktiven Uniform-Blocks, zwischen 0 und gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS) - 1.

Rückgabewert

Typ
string | null
Beschreibung
Der Name des Uniform-Blocks, wie er im Shader deklariert ist (der Blockname, nicht der Instanzname). Bei einem ungültigen Index gibt die Methode null zurück und setzt den Fehler gl.INVALID_VALUE.

Beispiele

Alle Uniform-Blöcke eines Programms auflisten

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

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

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

const compile = (type, src) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, src);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(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);

const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
for (let i = 0; i < count; i++) {
  console.log(i, gl.getActiveUniformBlockName(program, i));
}
0 Camera 1 Model (Reihenfolge implementierungsabhängig)

Blöcke automatisch an Binding-Points binden

// Annahme: gl und ein gelinktes program existieren bereits
const bindingPoints = { Camera: 0, Model: 1, Lights: 2 };

const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
for (let i = 0; i < count; i++) {
  const name = gl.getActiveUniformBlockName(program, i);
  const binding = bindingPoints[name];
  if (binding === undefined) {
    console.warn(`Unbekannter Uniform-Block: ${name}`);
    continue;
  }
  gl.uniformBlockBinding(program, i, binding);
  const size = gl.getActiveUniformBlockParameter(
    program, i, gl.UNIFORM_BLOCK_DATA_SIZE
  );
  console.log(`${name} → Binding ${binding}, ${size} Bytes`);
}
Camera → Binding 0, 128 Bytes Model → Binding 1, 64 Bytes

Ungültigen Index erkennen

const name = gl.getActiveUniformBlockName(program, 99);
console.log(name);
console.log(gl.getError() === gl.INVALID_VALUE);
null true

// Wichtig · Fallstricke

  • Nur WebGL 2: Die Methode gibt es ausschließlich auf WebGL2RenderingContext. Ein webgl-Kontext (WebGL 1) hat keine Uniform-Blöcke. Vorher prüfen, ob canvas.getContext('webgl2') nicht null liefert.
  • Blockname statt Instanzname: Bei uniform Camera { … } cam; gibt die Methode "Camera" zurück, nicht "cam". Bei Block-Arrays wie uniform Lights { … } lights[4]; erscheinen die Namen mit Index, zum Beispiel "Lights[0]".
  • Nur aktive Blöcke: Der Shader-Compiler kann Blöcke entfernen, die im Shader nicht benutzt werden. Solche Blöcke haben dann keinen Index. Die Reihenfolge der Indizes legt die Implementierung fest; man sollte sich nicht auf die Reihenfolge im Quelltext verlassen.
  • Das Programm muss gelinkt sein (gl.LINK_STATUS ist true), sonst sind die Ergebnisse ungültig.
  • Performance: Introspektionsaufrufe können die GPU-Pipeline synchronisieren. Namen und Indizes daher einmal nach dem Linken abfragen und zwischenspeichern, nicht in jedem Frame.
  • Kompatibilität: WebGL 2 läuft in Chrome, Edge, Firefox und Safari (ab 15). Wenn der Kontext verloren geht (webglcontextlost), gibt die Methode null zurück.