Signatur
Beschreibung
linkProgram() ist der letzte Schritt beim Erzeugen eines Shader-Programms in WebGL. Zuerst kompilierst du die Shader mit compileShader(), dann hängst du sie mit attachShader() an ein WebGLProgram. Danach bringt linkProgram() die beiden Shader zusammen: Die varying-Variablen des Vertex-Shaders werden den passenden Eingaben des Fragment-Shaders zugeordnet, Attribut- und Uniform-Positionen werden vergeben und der Maschinencode für die GPU wird erzeugt.
Die Methode gibt nichts zurück und löst bei einem Linkfehler keine Ausnahme aus. Ob das Linken geklappt hat, fragst du mit gl.getProgramParameter(program, gl.LINK_STATUS) ab. Die Fehlermeldung des Treibers bekommst du über gl.getProgramInfoLog(program).
Attribut-Positionen, die du mit bindAttribLocation() festlegst, gelten erst nach dem nächsten linkProgram()-Aufruf. Auch die Positionen von Uniforms und Attributen solltest du erst nach dem Linken abfragen, zum Beispiel mit getUniformLocation() und getAttribLocation(). Wird ein Programm, das gerade in Benutzung ist, neu gelinkt, gilt das neue Ergebnis nur, wenn das Linken erfolgreich war.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das Programm, das gelinkt werden soll. Es muss mit gl.createProgram() erzeugt worden sein, und es müssen ein Vertex- und ein Fragment-Shader angehängt sein. |
Rückgabewert
undefined). Den Erfolg prüfst du mit getProgramParameter(program, gl.LINK_STATUS).Beispiele
Shader kompilieren, anhängen und Programm linken
const canvas = document.createElement('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);
console.log('Gelinkt:', gl.getProgramParameter(program, gl.LINK_STATUS));
Wiederverwendbare Hilfsfunktion mit Fehlerbehandlung
const createProgram = (gl, vertexShader, fragmentShader) => {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const log = gl.getProgramInfoLog(program);
gl.deleteProgram(program);
throw new Error(`Programm konnte nicht gelinkt werden: ${log}`);
}
// Shader werden nach dem Linken nicht mehr gebraucht
gl.detachShader(program, vertexShader);
gl.detachShader(program, fragmentShader);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
return program;
};
Attribut-Position vor dem Linken festlegen
// Annahme: gl, vertexShader und fragmentShader sind vorhanden
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
// Muss VOR linkProgram() aufgerufen werden
gl.bindAttribLocation(program, 0, 'aPosition');
gl.linkProgram(program);
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
gl.useProgram(program);
console.log(gl.getAttribLocation(program, 'aPosition'));
const uColor = gl.getUniformLocation(program, 'uColor');
gl.uniform4f(uColor, 1.0, 0.5, 0.0, 1.0);
}
// Wichtig · Fallstricke
- Keine Ausnahme bei Fehlern: Wenn das Linken fehlschlägt, bleibt das stumm. Prüfe immer
LINK_STATUSund gibgetProgramInfoLog()aus. Häufige Ursachen sindvarying-Variablen, deren Namen oder Typen in den beiden Shadern nicht zusammenpassen, ein fehlender Shader oder zu viele Uniforms oder Attribute für die Hardware. - Performance: In vielen Browsern blockiert
linkProgram()nicht sofort. Erst die anschließende Abfrage vonLINK_STATUSwartet, bis das Linken fertig ist. Mit der ErweiterungKHR_parallel_shader_compilekannst duCOMPLETION_STATUS_KHRabfragen, ohne den Hauptthread zu blockieren. So lassen sich viele Programme parallel vorbereiten. - Wird ein Programm neu gelinkt, gehen alle Uniform-Werte verloren. Außerdem werden vorher abgefragte
WebGLUniformLocation-Objekte ungültig. - Ist
programkein gültigesWebGLProgram, entsteht der FehlerINVALID_VALUEoderINVALID_OPERATION. Den kannst du mitgl.getError()auslesen. - Die Methode gibt es auch in
WebGL2RenderingContext. Sie wird von allen modernen Browsern unterstützt.