Signatur
Beschreibung
Mit getUniform() fragt man bei der GPU bzw. dem WebGL-Treiber ab, welcher Wert gerade in einer Uniform-Variable eines Shader-Programms steht. Übergeben werden das Programm (WebGLProgram) und die Position der Uniform, die man vorher mit getUniformLocation() ermittelt hat.
Welchen Typ der Rückgabewert hat, hängt vom GLSL-Typ der Uniform ab: float ergibt eine number, vec3 ein Float32Array mit drei Elementen, ivec2 ein Int32Array, bool einen boolean, bvec4 ein Array aus Booleans, mat4 ein Float32Array mit 16 Elementen (spaltenweise) und Sampler (sampler2D, samplerCube) eine number mit der Nummer der Textur-Einheit.
Die Methode ist vor allem für Fehlersuche, Tests und Werkzeuge wie Shader-Inspektoren gedacht. Im Render-Loop sollte man sie nicht einsetzen: Jeder Aufruf kann die GPU-Pipeline synchronisieren und die Bildrate spürbar senken. Wer Uniform-Werte zur Laufzeit braucht, merkt sie sich besser selbst auf der JavaScript-Seite.
Wenn ein Array-Uniform (z. B. uniform vec3 lights[4]) abgefragt wird, liefert getUniform() immer nur ein einzelnes Element, nämlich das an der übergebenen Position. Für andere Elemente muss man die Position explizit anfragen, z. B. mit getUniformLocation(program, "lights[2]").
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das erfolgreich gelinkte Shader-Programm, zu dem die Uniform gehört. | |
| $location Pflicht | WebGLUniformLocation | Position der Uniform, ermittelt mit getUniformLocation() für genau dieses Programm. |
Rückgabewert
number für float/int/Sampler, boolean für bool, typisierte Arrays für Vektoren und Matrizen, boolean[] für bvecN. Uint32Array (für uint/uvecN) gibt es nur in WebGL2. Tritt ein Fehler auf, kommt null zurück.Beispiele
Gesetzten Farbwert zur Kontrolle auslesen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const compile = (type, src) => {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
return s;
};
const vs = compile(gl.VERTEX_SHADER, `
attribute vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }
`);
const fs = compile(gl.FRAGMENT_SHADER, `
precision mediump float;
uniform vec4 uColor;
uniform float uAlpha;
void main() { gl_FragColor = vec4(uColor.rgb, uColor.a * uAlpha); }
`);
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
gl.useProgram(program);
const colorLoc = gl.getUniformLocation(program, 'uColor');
const alphaLoc = gl.getUniformLocation(program, 'uAlpha');
gl.uniform4f(colorLoc, 1.0, 0.5, 0.0, 1.0);
gl.uniform1f(alphaLoc, 0.75);
console.log(gl.getUniform(program, colorLoc));
console.log(gl.getUniform(program, alphaLoc));
Alle aktiven Uniforms eines Programms ausgeben (Debug-Helfer)
// Erwartet ein gelinktes Programm 'program' und den Kontext 'gl'
const dumpUniforms = (gl, program) => {
const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
const result = {};
for (let i = 0; i < count; i++) {
const info = gl.getActiveUniform(program, i);
if (!info) continue;
const loc = gl.getUniformLocation(program, info.name);
const value = gl.getUniform(program, loc);
// Typisierte Arrays für eine lesbare Ausgabe umwandeln
result[info.name] = ArrayBuffer.isView(value) ? Array.from(value) : value;
}
return result;
};
console.table(dumpUniforms(gl, program));
Matrix und Sampler abfragen
// Shader enthält: uniform mat4 uModel; uniform sampler2D uTexture;
const modelLoc = gl.getUniformLocation(program, 'uModel');
const texLoc = gl.getUniformLocation(program, 'uTexture');
const identity = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]);
gl.uniformMatrix4fv(modelLoc, false, identity);
gl.uniform1i(texLoc, 2); // Textur-Einheit 2
console.log(gl.getUniform(program, modelLoc).length);
console.log(gl.getUniform(program, texLoc));
// Wichtig · Fallstricke
- Leistung:
getUniform()ist eine blockierende Abfrage und kann die GPU-Pipeline synchronisieren. Im Render-Loop sollte man sie nicht aufrufen; Werte besser selbst in JavaScript zwischenspeichern. - Die
WebGLUniformLocationmuss zum übergebenen Programm gehören. Ist das nicht der Fall, gibt es den FehlerINVALID_OPERATION. Nach erneutemlinkProgram()sind alte Positionen ungültig. - Ist das Programm nicht (erfolgreich) gelinkt, entsteht ebenfalls
INVALID_OPERATIONund der Rückgabewert istnull. Mitgl.getError()lässt sich prüfen, was schiefging. - Uniforms, die der Shader-Compiler als ungenutzt wegoptimiert hat, haben keine Position:
getUniformLocation()liefert dannnull. Das ist kein Fehler im eigenen Code. - Rückgabewerte für Vektoren und Matrizen sind neue typisierte Arrays. Wer sie verändert, ändert dadurch nicht die Uniform auf der GPU.
- Die Methode gibt es seit WebGL 1.0 in allen aktuellen Browsern. In
WebGL2RenderingContextkommen zusätzlich die Typenuint/uvecN(Uint32Array) und nicht-quadratische Matrizen dazu.