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

WebGLRenderingContext.createProgram()

Methode

Erstellt und initialisiert ein leeres <code>WebGLProgram</code>-Objekt, an das anschließend Vertex- und Fragment-Shader angehängt und gelinkt werden.

seit JavaScript Baseline: alle Browser (WebGL 1.0) Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.createProgram()

Beschreibung

Mit createProgram() legen Sie ein neues, leeres Shader-Programm an. Ein WebGLProgram verbindet genau einen Vertex-Shader mit einem Fragment-Shader. Beide zusammen bilden die programmierbare Grafik-Pipeline, die bei jedem Zeichenaufruf (drawArrays(), drawElements()) auf der GPU ausgeführt wird.

Der übliche Ablauf sieht so aus:

  • Shader mit createShader(), shaderSource() und compileShader() erzeugen und kompilieren,
  • Programm mit createProgram() anlegen,
  • beide Shader mit attachShader() anhängen,
  • das Programm mit linkProgram() linken und den Status über getProgramParameter(program, gl.LINK_STATUS) prüfen,
  • das Programm vor dem Zeichnen mit useProgram() aktivieren.

Die Methode selbst nimmt keine Argumente entgegen und wirft bei Fehlern keine Ausnahme. Ob ein Programm tatsächlich benutzbar ist, erfahren Sie erst nach dem Linken. Die Methode gibt es auch in WebGL2RenderingContext, dort verhält sie sich genauso.

Rückgabewert

Typ
WebGLProgram | null
Beschreibung
Ein neues, leeres WebGLProgram-Objekt. Ist der Kontext verloren gegangen (context lost), kommt null zurück.

Beispiele

Minimales Programm aus zwei Shadern erstellen

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;
  void main() {
    gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
  }`;

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

console.log(program instanceof WebGLProgram);
true

Wiederverwendbare Hilfsfunktion mit Fehlerbehandlung

const createShader = (gl, type, source) => {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    const log = gl.getShaderInfoLog(shader);
    gl.deleteShader(shader);
    throw new Error(`Shader-Fehler: ${log}`);
  }
  return shader;
};

const createProgramFromSources = (gl, vsSource, fsSource) => {
  const vs = createShader(gl, gl.VERTEX_SHADER, vsSource);
  const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

  const program = gl.createProgram();
  if (!program) throw new Error('Kontext verloren – kein Programm erstellt');

  gl.attachShader(program, vs);
  gl.attachShader(program, fs);
  gl.linkProgram(program);

  // Shader werden nach dem Linken nicht mehr gebraucht
  gl.detachShader(program, vs);
  gl.detachShader(program, fs);
  gl.deleteShader(vs);
  gl.deleteShader(fs);

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    const log = gl.getProgramInfoLog(program);
    gl.deleteProgram(program);
    throw new Error(`Link-Fehler: ${log}`);
  }
  return program;
};

Programm verwenden und Attribut-/Uniform-Positionen abfragen

const gl = document.querySelector('canvas').getContext('webgl');

const program = createProgramFromSources(gl, `
  attribute vec2 aPosition;
  void main() { gl_Position = vec4(aPosition, 0.0, 1.0); }
`, `
  precision mediump float;
  uniform vec4 uColor;
  void main() { gl_FragColor = uColor; }
`);

gl.useProgram(program);
const posLoc = gl.getAttribLocation(program, 'aPosition');
const colorLoc = gl.getUniformLocation(program, 'uColor');
gl.uniform4f(colorLoc, 0.2, 0.6, 1.0, 1.0);

console.log('aPosition-Index:', posLoc);

// Aufräumen, wenn das Programm nicht mehr gebraucht wird
// gl.deleteProgram(program);
aPosition-Index: 0

// Wichtig · Fallstricke

  • Kein Fehler beim Anlegen: createProgram() meldet Probleme nicht selbst. Prüfen Sie nach linkProgram() immer gl.getProgramParameter(program, gl.LINK_STATUS) und lesen Sie bei Bedarf gl.getProgramInfoLog(program) aus. Wird das Programm nicht gelinkt, führt useProgram() zu INVALID_OPERATION.
  • Context Loss: Geht der WebGL-Kontext verloren (Ereignis webglcontextlost), gibt die Methode null zurück, und alle vorhandenen Programme sind ungültig. Nach webglcontextrestored müssen Sie alle Programme neu erzeugen.
  • Speicher: Programme belegen GPU-Ressourcen. Nicht mehr benötigte Programme geben Sie mit deleteProgram() frei. Die Shader können Sie nach dem erfolgreichen Linken mit detachShader()/deleteShader() entfernen.
  • Performance: Linken ist teuer. Erzeugen Sie Programme deshalb einmalig beim Start und nicht in jedem Frame. Wechsel per useProgram() kosten deutlich weniger.
  • Kompatibilität: Die Methode wird in allen modernen Browsern unterstützt, sowohl in WebGL 1 als auch in WebGL 2. Sie steht auch in OffscreenCanvas-Kontexten in Web Workern zur Verfügung.