Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.getUniform()

WebGLRenderingContext.getUniform()

Methode

Liest den aktuellen Wert einer Uniform-Variable eines gelinkten Shader-Programms an der angegebenen <code>WebGLUniformLocation</code> aus.

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

Signatur

WebGLRenderingContext.prototype.getUniform(program, location)

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

Typ
number | boolean | Float32Array | Int32Array | Uint32Array | boolean[] | null
Beschreibung
Der aktuelle Wert der Uniform. Der Typ richtet sich nach dem GLSL-Typ: 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));
Float32Array(4) [1, 0.5, 0, 1] 0.75

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));
{ uColor: [1, 0.5, 0, 1], uAlpha: 0.75 }

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));
16 2

// 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 WebGLUniformLocation muss zum übergebenen Programm gehören. Ist das nicht der Fall, gibt es den Fehler INVALID_OPERATION. Nach erneutem linkProgram() sind alte Positionen ungültig.
  • Ist das Programm nicht (erfolgreich) gelinkt, entsteht ebenfalls INVALID_OPERATION und der Rückgabewert ist null. Mit gl.getError() lässt sich prüfen, was schiefging.
  • Uniforms, die der Shader-Compiler als ungenutzt wegoptimiert hat, haben keine Position: getUniformLocation() liefert dann null. 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 WebGL2RenderingContext kommen zusätzlich die Typen uint/uvecN (Uint32Array) und nicht-quadratische Matrizen dazu.