Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.getActiveUniform()

WebGLRenderingContext.getActiveUniform()

Methode

Liefert ein <code>WebGLActiveInfo</code>-Objekt mit Name, Typ und Größe der aktiven Uniform-Variablen an einem bestimmten Index eines gelinkten Shader-Programms.

seit JavaScript WebGL 1.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.getActiveUniform(program, index)

Beschreibung

getActiveUniform() fragt Informationen über eine aktive Uniform-Variable eines gelinkten WebGLProgram ab. Aktiv heißt, dass der Shader-Compiler die Uniform tatsächlich verwendet und nicht wegoptimiert hat. Das Ergebnis ist ein WebGLActiveInfo-Objekt mit den schreibgeschützten Eigenschaften name, type (GL-Enum wie gl.FLOAT_MAT4 oder gl.SAMPLER_2D) und size (Anzahl der Elemente, bei Arrays > 1).

Typischerweise wird die Methode zusammen mit gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) in einer Schleife verwendet, um alle Uniforms eines Programms automatisch zu ermitteln (Shader-Reflection). Frameworks wie three.js oder twgl bauen damit Tabellen aus Uniform-Namen, Locations und passenden Setter-Funktionen auf, sodass man Uniforms nicht per Hand verwalten muss.

Die Indizes laufen von 0 bis ACTIVE_UNIFORMS - 1. Sie sind keine Uniform-Locations: Um einen Wert zu setzen, benötigt man weiterhin gl.getUniformLocation(program, info.name). Bei Uniform-Arrays enthält name das Suffix [0], bei Structs werden die einzelnen Felder als eigene Einträge geliefert (z. B. u_light.color).

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram Das gelinkte Shader-Programm, dessen Uniforms abgefragt werden (vorher gl.linkProgram() aufrufen).
$index Pflicht GLuint (number) Index der aktiven Uniform, zwischen 0 und gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) - 1.

Rückgabewert

Typ
WebGLActiveInfo | null
Beschreibung
Ein WebGLActiveInfo-Objekt mit name (string), type (GLenum) und size (number). Bei ungültigem Index oder Fehler null; zusätzlich wird ein GL-Fehler (z. B. INVALID_VALUE) gesetzt.

Beispiele

Alle aktiven Uniforms auflisten

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

const vsSource = `
  attribute vec4 a_position;
  uniform mat4 u_matrix;
  void main() { gl_Position = u_matrix * a_position; }
`;
const fsSource = `
  precision mediump float;
  uniform vec4 u_color;
  uniform float u_weights[3];
  void main() { gl_FragColor = u_color * (u_weights[0] + u_weights[1] + u_weights[2]); }
`;

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);

const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < count; i++) {
  const { name, type, size } = gl.getActiveUniform(program, i);
  console.log(`${i}: ${name} type=0x${type.toString(16)} size=${size}`);
}
0: u_matrix type=0x8b5c size=1 1: u_color type=0x8b52 size=1 2: u_weights[0] type=0x1406 size=3 (Reihenfolge ist implementierungsabhängig)

Uniform-Tabelle mit Locations aufbauen

const getUniforms = (gl, program) => {
  const uniforms = {};
  const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  for (let i = 0; i < count; i++) {
    const info = gl.getActiveUniform(program, i);
    if (!info) continue;
    // Array-Suffix "[0]" für einen sauberen Schlüssel entfernen
    const baseName = info.name.replace(/\[0\]$/, '');
    uniforms[baseName] = {
      type: info.type,
      size: info.size,
      location: gl.getUniformLocation(program, info.name)
    };
  }
  return uniforms;
};

const uniforms = getUniforms(gl, program);
gl.useProgram(program);
gl.uniform4fv(uniforms.u_color.location, [1, 0.5, 0, 1]);
console.log(Object.keys(uniforms));
["u_matrix", "u_color", "u_weights"]

GL-Typ in lesbaren Namen übersetzen

const typeNames = {
  [gl.FLOAT]: 'float',
  [gl.FLOAT_VEC2]: 'vec2',
  [gl.FLOAT_VEC3]: 'vec3',
  [gl.FLOAT_VEC4]: 'vec4',
  [gl.FLOAT_MAT4]: 'mat4',
  [gl.SAMPLER_2D]: 'sampler2D'
};

const info = gl.getActiveUniform(program, 0);
console.log(`${typeNames[info.type] ?? info.type} ${info.name}`);
mat4 u_matrix

// Wichtig · Fallstricke

  • Wegoptimierte Uniforms: Im Shader deklarierte, aber nicht genutzte Uniforms tauchen nicht auf. ACTIVE_UNIFORMS kann daher kleiner sein als erwartet – Code sollte fehlende Einträge verkraften.
  • Index ≠ Location: Der Index ist nur für die Abfrage gedacht. Werte setzt man über getUniformLocation(); die Reihenfolge der Indizes ist implementierungsabhängig.
  • Arrays: name endet auf [0], size gibt die (ggf. durch Optimierung verkürzte) Länge an. Einzelne Elemente adressiert man per getUniformLocation(program, 'u_arr[2]').
  • Programm muss gelinkt sein: Vor linkProgram() oder bei fehlgeschlagenem Linken (LINK_STATUS prüfen) sind die Ergebnisse ungültig. Bei ungültigem Index wird null zurückgegeben und INVALID_VALUE gesetzt.
  • Performance: Reflection einmalig nach dem Linken durchführen und cachen, nicht in jedem Frame aufrufen – solche Abfragen können die GPU-Pipeline synchronisieren.
  • Kompatibilität: In allen Browsern mit WebGL 1 verfügbar; in WebGL2RenderingContext identisch, dort zusätzlich getActiveUniforms() und Uniform-Blöcke.
  • Nach Kontextverlust (webglcontextlost) liefert die Methode null.