Signatur
Beschreibung
WebGLUniformLocation ist ein undurchsichtiges Handle der WebGL-API. Es verweist auf eine Uniform-Variable (z. B. uniform mat4 uModelView; oder uniform sampler2D uTexture;) in einem bereits gelinkten WebGLProgram. Das Interface hat weder eigene Methoden noch Eigenschaften und kann nicht per new erzeugt werden.
Man erhält eine Instanz über gl.getUniformLocation(program, name). Das zurückgegebene Objekt übergibt man anschließend an die gl.uniform*()-Methoden – etwa uniform1f, uniform3fv, uniform1i oder uniformMatrix4fv –, um Werte in den Shader zu schreiben. Mit gl.getUniform(program, location) lässt sich der aktuelle Wert auch wieder auslesen.
In der Praxis fragt man die Positionen einmalig nach dem Linken ab und speichert sie zwischen, denn getUniformLocation sucht über einen String und ist deshalb vergleichsweise teuer. Im Render-Loop setzt man dann nur noch die Werte. Eine Position gilt immer nur für genau das Programm, aus dem sie stammt.
Rückgabewert
WebGLRenderingContext.getUniformLocation() geliefert. Ist die Uniform nicht vorhanden oder vom Shader-Compiler wegoptimiert worden, ist der Wert null.Beispiele
Uniform-Position abfragen und Farbe setzen
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const vsSource = `
attribute vec2 aPosition;
void main() { gl_Position = vec4(aPosition, 0.0, 1.0); }
`;
const fsSource = `
precision mediump float;
uniform vec4 uColor;
void main() { gl_FragColor = uColor; }
`;
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);
// WebGLUniformLocation erhalten
const uColor = gl.getUniformLocation(program, 'uColor');
console.log(uColor instanceof WebGLUniformLocation);
gl.useProgram(program); // Programm muss aktiv sein!
gl.uniform4f(uColor, 1.0, 0.5, 0.0, 1.0); // Orange
Positionen zwischenspeichern und im Render-Loop nutzen
// Einmalig nach linkProgram()
const uniforms = {
time: gl.getUniformLocation(program, 'uTime'),
matrix: gl.getUniformLocation(program, 'uMatrix'),
texture: gl.getUniformLocation(program, 'uTexture'),
};
const identity = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]);
const render = (t) => {
gl.useProgram(program);
gl.uniform1f(uniforms.time, t / 1000);
gl.uniformMatrix4fv(uniforms.matrix, false, identity);
gl.uniform1i(uniforms.texture, 0); // Textur-Einheit 0
gl.drawArrays(gl.TRIANGLES, 0, 3);
requestAnimationFrame(render);
};
requestAnimationFrame(render);
Fehlende Uniforms erkennen und Wert auslesen
const loc = gl.getUniformLocation(program, 'uColor');
if (loc === null) {
console.warn('Uniform uColor fehlt oder wurde wegoptimiert');
} else {
gl.useProgram(program);
gl.uniform4fv(loc, [0.2, 0.4, 0.6, 1.0]);
const value = gl.getUniform(program, loc);
console.log(Array.from(value).map((v) => v.toFixed(1)));
}
// Array-Elemente und Struct-Felder haben eigene Positionen
const light0 = gl.getUniformLocation(program, 'uLights[0].position');
// Wichtig · Fallstricke
- Wegoptimierte Uniforms: Der GLSL-Compiler entfernt Uniforms, die sich nicht auf die Ausgabe auswirken.
getUniformLocationgibt dannnullzurück. Einuniform*()-Aufruf mitnullwird still ignoriert und löst keinen Fehler aus – Tippfehler im Namen bleiben so leicht unbemerkt. - Programm muss aktiv sein:
gl.uniform*()wirkt immer auf das mitgl.useProgram()aktivierte Programm. Gehört die Position zu einem anderen Programm, entstehtINVALID_OPERATION. - Nicht übertragbar: Positionen gelten nur für das Programm, aus dem sie stammen. Nach einem erneuten
linkProgram()und nach einem Kontextverlust (webglcontextlost) werden sie ungültig und müssen neu abgefragt werden. - Typen müssen passen: Sampler (
sampler2D) setzt man mituniform1i(Index der Textur-Einheit), Matrizen mituniformMatrix*fv. In WebGL 1 muss der Parametertransposefalsesein. - Kein Zahlenwert: Anders als in nativem OpenGL ist die Position keine Ganzzahl, sondern ein Objekt. Man kann nicht damit rechnen – für Array-Elemente fragt man daher z. B.
'uArr[2]'separat ab. - Kompatibilität: Wird in allen modernen Browsern unterstützt, sowohl in
WebGLRenderingContextals auch inWebGL2RenderingContext. In Web Workern ist es überOffscreenCanvasverfügbar.