Signatur
Beschreibung
Die Methodenfamilie uniform[1234][fi][v]() überträgt Werte aus JavaScript an uniform-Variablen in Vertex- und Fragment-Shadern. Uniforms bleiben für alle Vertices bzw. Fragmente eines Zeichenaufrufs gleich und eignen sich damit für Zeit, Auflösung, Farben, Lichtpositionen oder Textur-Einheiten.
Der Methodenname legt fest, welchen Typ die Werte haben:
- Ziffer 1–4: Anzahl der Komponenten, also
float/intbzw.vec2,vec3,vec4(oderivec2..4,bvec2..4). foderi: Gleitkomma- oder Ganzzahlwerte. Fürbool/bvecgehen beide Varianten, fürsampler2D/samplerCubenuruniform1i.v: Die Werte werden als Array bzw.Float32Array/Int32Arrayübergeben statt als einzelne Argumente. So lassen sich auch Uniform-Arrays (z. B.uniform vec3 uLights[4]) auf einmal befüllen.
Die Methoden wirken immer auf das Programm, das gerade mit gl.useProgram() aktiviert ist. Die nötige WebGLUniformLocation liefert gl.getUniformLocation(program, name). Für Matrizen gibt es eigene Methoden (uniformMatrix[234]fv). In WebGL 2 kommen die Varianten uniform[1234]ui[v] für vorzeichenlose Ganzzahlen dazu.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $location Pflicht | WebGLUniformLocation | null | Ort der Uniform-Variablen, geliefert von gl.getUniformLocation(). Bei null passiert nichts, und es gibt keinen Fehler. |
|
| $v0, v1, v2, v3 Pflicht | number | Nur bei den Varianten ohne v: 1 bis 4 einzelne Werte, je nach Ziffer im Methodennamen. Bei f Gleitkommazahlen, bei i Ganzzahlen (Nachkommastellen werden abgeschnitten). |
|
| $value Pflicht | Float32Array | Int32Array | number[] | Nur bei den v-Varianten: Array mit den Werten. Die Länge muss ein Vielfaches der Komponentenanzahl sein, z. B. 3·n bei uniform3fv. Für fv dient ein Float32Array, für iv ein Int32Array. |
Rückgabewert
undefined). Fehler lassen sich über gl.getError() abfragen.Beispiele
Zeit und Auflösung pro Frame setzen
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const vsSource = `
attribute vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }`;
const fsSource = `
precision mediump float;
uniform float uTime;
uniform vec2 uResolution;
void main() {
vec2 uv = gl_FragCoord.xy / uResolution;
gl_FragColor = vec4(uv, 0.5 + 0.5 * sin(uTime), 1.0);
}`;
const compile = (type, src) => {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
return s;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
gl.useProgram(program);
// Vollbild-Rechteck aus zwei Dreiecken
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1]), gl.STATIC_DRAW);
const aPos = gl.getAttribLocation(program, 'aPos');
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
// Locations einmal holen, nicht in jedem Frame
const uTime = gl.getUniformLocation(program, 'uTime');
const uResolution = gl.getUniformLocation(program, 'uResolution');
const render = (t) => {
gl.uniform1f(uTime, t / 1000);
gl.uniform2f(uResolution, canvas.width, canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
};
requestAnimationFrame(render);
Farbe als Vektor mit uniform4fv übergeben
// Voraussetzung: im Fragment-Shader gibt es `uniform vec4 uColor;`
const uColor = gl.getUniformLocation(program, 'uColor');
gl.useProgram(program);
const red = new Float32Array([1.0, 0.0, 0.0, 1.0]);
gl.uniform4fv(uColor, red);
// Gleichwertig mit einzelnen Argumenten:
gl.uniform4f(uColor, 1.0, 0.0, 0.0, 1.0);
console.log(gl.getUniform(program, uColor));
Textur-Einheit und Uniform-Array befüllen
// Shader: uniform sampler2D uTexture; uniform vec3 uLights[3];
gl.useProgram(program);
// Sampler bekommen die Nummer der Textur-Einheit, nur mit uniform1i möglich
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.uniform1i(gl.getUniformLocation(program, 'uTexture'), 0);
// Drei vec3-Lichtpositionen in einem Aufruf: 3 × 3 = 9 Werte
const lights = new Float32Array([
0.0, 5.0, 0.0,
3.0, 2.0, -1.0,
-3.0, 2.0, 1.0,
]);
gl.uniform3fv(gl.getUniformLocation(program, 'uLights'), lights);
// Wichtig · Fallstricke
- Zuerst
useProgram(): Die Werte landen im gerade aktiven Programm. Ohne passendes Programm kommt es zum FehlerINVALID_OPERATION, oder die Werte gehen an das falsche Programm. - Typ und Größe müssen passen: Wenn Methode und GLSL-Typ nicht übereinstimmen, z. B.
uniform1ffür einenintoderuniform3ffür einenvec4, gibt esINVALID_OPERATION. Das passiert ohne Exception und ist nur übergl.getError()sichtbar. - Sampler dürfen nur mit
uniform1i/uniform1ivgesetzt werden. - Weg-optimierte Uniforms: Nutzt der Shader eine Uniform gar nicht, entfernt der Compiler sie.
getUniformLocation()gibt dannnullzurück, und alle Aufrufe werden ohne Meldung ignoriert. Das ist erlaubt, erschwert aber die Fehlersuche. - Performance: Locations einmal nach dem Linken holen und zwischenspeichern. Typisierte Arrays bei
v-Varianten wiederverwenden, statt sie in jedem Frame neu anzulegen. - Werte bleiben erhalten: Uniforms behalten ihren Wert pro Programm, bis sie überschrieben werden. Nach erneutem
linkProgram()werden sie auf 0 zurückgesetzt. - Kompatibilität: Wird in allen modernen Browsern unterstützt. Die Varianten
uniform[1234]ui[v]und die zusätzlichen ParametersrcOffset/srcLengthbei denv-Varianten gibt es nur inWebGL2RenderingContext.