Signatur
Beschreibung
compileShader() übersetzt den GLSL-Quelltext eines Shader-Objekts in eine Form, die die Grafikkarte ausführen kann. Der Ablauf ist immer gleich: Mit createShader() legst du einen Vertex- oder Fragment-Shader an, mit shaderSource() übergibst du den Quelltext, und mit compileShader() kompilierst du ihn. Danach wird der Shader per attachShader() an ein Programm gehängt und mit linkProgram() gelinkt.
Die Methode gibt nichts zurück und wirft bei Syntaxfehlern keine Ausnahme. Ob das Kompilieren geklappt hat, musst du selbst mit gl.getShaderParameter(shader, gl.COMPILE_STATUS) prüfen. Schlägt es fehl, liefert gl.getShaderInfoLog(shader) die Fehlermeldung des Treibers mit Zeilennummern.
Die Methode gibt es genauso in WebGL2RenderingContext. Dort kannst du zusätzlich GLSL ES 3.00 verwenden (erste Zeile #version 300 es). Wenn die Erweiterung KHR_parallel_shader_compile verfügbar ist, können Browser das Kompilieren im Hintergrund erledigen. Den Status fragt man dann erst ab, wenn er wirklich gebraucht wird.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $shader Pflicht | WebGLShader | Ein Shader-Objekt, das mit gl.createShader(gl.VERTEX_SHADER) oder gl.createShader(gl.FRAGMENT_SHADER) erzeugt wurde und dem per gl.shaderSource() schon Quelltext zugewiesen ist. |
Rückgabewert
undefined). Das Ergebnis wird über getShaderParameter(shader, gl.COMPILE_STATUS) abgefragt.Beispiele
Shader kompilieren mit Fehlerprüfung
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
const compile = (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 vs = compile(gl, gl.VERTEX_SHADER, `
attribute vec4 aPosition;
void main() { gl_Position = aPosition; }
`);
console.log(gl.getShaderParameter(vs, gl.COMPILE_STATUS));
Fehlerhaften Shader diagnostizieren
const gl = document.createElement('canvas').getContext('webgl');
const fs = gl.createShader(gl.FRAGMENT_SHADER);
// Fehler: precision fehlt, Semikolon fehlt
gl.shaderSource(fs, 'void main() { gl_FragColor = vec4(1.0) }');
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(fs));
}
Vollständiges Programm aus Vertex- und Fragment-Shader
const gl = document.querySelector('canvas').getContext('webgl');
const vsSource = `
attribute vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }`;
const fsSource = `
precision mediump float;
uniform vec4 uColor;
void main() { gl_FragColor = uColor; }`;
const makeShader = (type, src) => {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
return s;
};
const program = gl.createProgram();
gl.attachShader(program, makeShader(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, makeShader(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
// Status erst nach dem Linken prüfen – so kann der Treiber parallel arbeiten
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
} else {
gl.useProgram(program);
console.log('Programm bereit');
}
// Wichtig · Fallstricke
- Keine Ausnahme bei Fehlern: Syntax- und Typfehler im GLSL-Code merkst du nur, wenn du
COMPILE_STATUSprüfst. Ohne diese Prüfung scheitert später erstlinkProgram()oder es wird einfach nichts gezeichnet. - Leistung: Das Kompilieren kann den Haupt-Thread spürbar blockieren, wenn du den Status direkt danach abfragst (ein synchroner Abgleich mit der GPU). Besser ist es, alle Shader zu kompilieren, die Programme zu linken und erst dann
LINK_STATUSzu prüfen. MitKHR_parallel_shader_compilekannst duCOMPLETION_STATUS_KHRauch ohne Blockieren abfragen. - Fragment-Shader in WebGL 1 brauchen eine Präzisionsangabe (z. B.
precision mediump float;), sonst schlägt das Kompilieren fehl. - Bei GLSL ES 3.00 (WebGL 2) muss
#version 300 esganz am Anfang stehen. Davor dürfen weder Leerzeilen noch Leerzeichen kommen – Vorsicht bei Template-Literalen. - Der Inhalt von
getShaderInfoLog()hängt vom Browser und vom Treiber ab. Verlass dich also nicht auf einen bestimmten Wortlaut. - Wenn der Kontext verloren geht (
webglcontextlost), werden alle Shader ungültig und müssen neu kompiliert werden. - Nicht mehr gebrauchte Shader kannst du nach dem Linken mit
deleteShader()freigeben.