Signatur
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
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}`);
}
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));
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}`);
// Wichtig · Fallstricke
- Wegoptimierte Uniforms: Im Shader deklarierte, aber nicht genutzte Uniforms tauchen nicht auf.
ACTIVE_UNIFORMSkann 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:
nameendet auf[0],sizegibt die (ggf. durch Optimierung verkürzte) Länge an. Einzelne Elemente adressiert man pergetUniformLocation(program, 'u_arr[2]'). - Programm muss gelinkt sein: Vor
linkProgram()oder bei fehlgeschlagenem Linken (LINK_STATUSprüfen) sind die Ergebnisse ungültig. Bei ungültigem Index wirdnullzurückgegeben undINVALID_VALUEgesetzt. - 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
WebGL2RenderingContextidentisch, dort zusätzlichgetActiveUniforms()und Uniform-Blöcke. - Nach Kontextverlust (
webglcontextlost) liefert die Methodenull.