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

WebGLRenderingContext.useProgram()

Methode

Setzt das angegebene <code>WebGLProgram</code> als aktives Shader-Programm für alle folgenden Zeichen- und Uniform-Aufrufe.

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

Signatur

WebGLRenderingContext.prototype.useProgram(program)

Beschreibung

useProgram() legt fest, welches gelinkte Shader-Programm (Vertex- und Fragment-Shader) der WebGL-Kontext beim nächsten drawArrays() oder drawElements() verwendet. Das Programm bleibt so lange aktiv, bis Sie useProgram() mit einem anderen Programm oder mit null aufrufen.

Uniform-Werte setzen Sie mit uniform*(). Diese Aufrufe wirken immer auf das gerade aktive Programm. Deshalb müssen Sie useProgram() aufrufen, bevor Sie Uniforms eines Programms setzen. Uniform-Werte werden pro Programm gespeichert und bleiben beim Wechsel zwischen Programmen erhalten.

Wenn eine Szene mehrere Materialien oder Effekte hat, wechseln Sie typischerweise pro Objektgruppe das Programm. Weil ein Programmwechsel eine vergleichsweise teure Zustandsänderung ist, lohnt es sich, Zeichenaufrufe nach Programm zu sortieren.

Die Methode gibt es auch in WebGL2RenderingContext mit identischem Verhalten.

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram | null Ein erfolgreich mit linkProgram() gelinktes Programm. Mit null ist danach kein Programm mehr aktiv. Zeichenaufrufe erzeugen dann einen Fehler.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Fehler lesen Sie über gl.getError() aus.

Beispiele

Programm erstellen, linken und aktivieren

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, source) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  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);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  throw new Error(gl.getProgramInfoLog(program));
}

gl.useProgram(program);
console.log(gl.getParameter(gl.CURRENT_PROGRAM) === program);
true

Uniforms erst nach useProgram() setzen

// Annahme: 'program' ist gelinkt (siehe erstes Beispiel)
const uColor = gl.getUniformLocation(program, 'uColor');

gl.useProgram(program);           // zuerst aktivieren …
gl.uniform4f(uColor, 1, 0, 0, 1); // … dann Uniform setzen (Rot)

const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]), gl.STATIC_DRAW);

const aPosition = gl.getAttribLocation(program, 'aPosition');
gl.enableVertexAttribArray(aPosition);
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);

gl.drawArrays(gl.TRIANGLES, 0, 3);
console.log(gl.getError() === gl.NO_ERROR);
true

Zwischen mehreren Programmen wechseln

// Objekte nach Programm gruppieren, damit möglichst selten gewechselt wird
const renderScene = (gl, batches) => {
  for (const { program, objects } of batches) {
    gl.useProgram(program);
    for (const obj of objects) {
      gl.uniformMatrix4fv(obj.uModelLoc, false, obj.modelMatrix);
      gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
      gl.vertexAttribPointer(obj.aPosLoc, 3, gl.FLOAT, false, 0, 0);
      gl.enableVertexAttribArray(obj.aPosLoc);
      gl.drawArrays(gl.TRIANGLES, 0, obj.vertexCount);
    }
  }
  gl.useProgram(null); // optional: Zustand zurücksetzen
};

// Wichtig · Fallstricke

  • Nicht gelinktes Programm: Ist das Linken fehlgeschlagen, löst useProgram() den Fehler INVALID_OPERATION aus. Prüfen Sie deshalb vorher gl.getProgramParameter(program, gl.LINK_STATUS).
  • Uniforms: uniform*()-Aufrufe ohne aktives Programm oder mit einer Location aus einem anderen Programm erzeugen INVALID_OPERATION. Das passiert oft unbemerkt, weil WebGL keine Ausnahmen wirft.
  • Kontextverlust: Nach webglcontextlost sind alle WebGLProgram-Objekte ungültig und müssen neu erstellt werden.
  • Löschen: Wenn Sie deleteProgram() auf das aktive Programm aufrufen, wird es erst tatsächlich gelöscht, sobald es nicht mehr aktiv ist.
  • Leistung: Häufige Programmwechsel kosten Zeit. Sortieren Sie deshalb Zeichenaufrufe nach Programm.
  • Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt, auch in WebGL2RenderingContext.