Signatur
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()undcompileShader()erzeugen und kompilieren, - Programm mit
createProgram()anlegen, - beide Shader mit
attachShader()anhängen, - das Programm mit
linkProgram()linken und den Status übergetProgramParameter(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
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);
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);
// Wichtig · Fallstricke
- Kein Fehler beim Anlegen:
createProgram()meldet Probleme nicht selbst. Prüfen Sie nachlinkProgram()immergl.getProgramParameter(program, gl.LINK_STATUS)und lesen Sie bei Bedarfgl.getProgramInfoLog(program)aus. Wird das Programm nicht gelinkt, führtuseProgram()zuINVALID_OPERATION. - Context Loss: Geht der WebGL-Kontext verloren (Ereignis
webglcontextlost), gibt die Methodenullzurück, und alle vorhandenen Programme sind ungültig. Nachwebglcontextrestoredmü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 mitdetachShader()/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.