Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.uniform[1234][fi][v]()

WebGLRenderingContext.uniform[1234][fi][v]()

Methode

Setzt den Wert einer Uniform-Variablen im aktuell aktiven Shader-Programm – als einzelne Zahlen (<code>uniform3f</code>) oder als Array (<code>uniform3fv</code>).

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

Signatur

WebGLRenderingContext.prototype.uniform[1234][fi][v](location, v0, v1, v2, v3 | value)

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/int bzw. vec2, vec3, vec4 (oder ivec2..4, bvec2..4).
  • f oder i: Gleitkomma- oder Ganzzahlwerte. Für bool/bvec gehen beide Varianten, für sampler2D/samplerCube nur uniform1i.
  • 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

Typ
void
Beschreibung
Kein 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));
Float32Array(4) [1, 0, 0, 1]

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 Fehler INVALID_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. uniform1f für einen int oder uniform3f für einen vec4, gibt es INVALID_OPERATION. Das passiert ohne Exception und ist nur über gl.getError() sichtbar.
  • Sampler dürfen nur mit uniform1i/uniform1iv gesetzt werden.
  • Weg-optimierte Uniforms: Nutzt der Shader eine Uniform gar nicht, entfernt der Compiler sie. getUniformLocation() gibt dann null zurü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 Parameter srcOffset/srcLength bei den v-Varianten gibt es nur in WebGL2RenderingContext.