Signatur
Beschreibung
detachShader() ist das Gegenstück zu attachShader(): Die Methode löst die Verbindung zwischen einem Shader-Objekt (Vertex- oder Fragment-Shader) und einem Programm-Objekt. Das bereits gelinkte Programm bleibt voll funktionsfähig, denn beim Aufruf von linkProgram() wurde der ausführbare Code schon erzeugt.
Typischer Einsatz ist das Aufräumen nach dem Linken. Nach einem erfolgreichen linkProgram() braucht man die Shader-Objekte nicht mehr. Mit detachShader() und anschließendem deleteShader() kann der Treiber den Speicher für Quelltext und Zwischencode freigeben. Ein Shader, der mit deleteShader() nur zum Löschen markiert ist, wird erst dann wirklich freigegeben, wenn er an kein Programm mehr angehängt ist.
Die Methode hilft außerdem beim Austauschen einzelner Shader, etwa beim Hot-Reload in Entwicklungs-Werkzeugen: alten Shader abhängen, neuen anhängen, Programm neu linken.
Die Methode gibt es genauso in WebGL2RenderingContext.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $program Pflicht | WebGLProgram | Das Programm-Objekt, von dem der Shader abgehängt werden soll. | |
| $shader Pflicht | WebGLShader | Der Vertex- oder Fragment-Shader, der entfernt werden soll. Er muss vorher mit attachShader() an program angehängt worden sein. |
Rückgabewert
undefined). Fehler meldet die Methode über gl.getError().Beispiele
Shader nach dem Linken abhängen und löschen
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
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 vs = compile(gl.VERTEX_SHADER, `
attribute vec2 pos;
void main() { gl_Position = vec4(pos, 0.0, 1.0); }`);
const fs = compile(gl.FRAGMENT_SHADER, `
precision mediump float;
void main() { gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); }`);
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
// Aufräumen: Das Programm bleibt nutzbar
gl.detachShader(program, vs);
gl.detachShader(program, fs);
gl.deleteShader(vs);
gl.deleteShader(fs);
console.log(gl.getProgramParameter(program, gl.ATTACHED_SHADERS));
Fragment-Shader zur Laufzeit austauschen (Hot-Reload)
// Voraussetzung: gl, program, compile() und der alte Shader oldFs sind vorhanden
const swapFragmentShader = (gl, program, oldFs, newSource) => {
const newFs = compile(gl.FRAGMENT_SHADER, newSource);
gl.detachShader(program, oldFs);
gl.attachShader(program, newFs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Linken fehlgeschlagen:', gl.getProgramInfoLog(program));
return oldFs;
}
gl.deleteShader(oldFs);
return newFs;
};
Angehängte Shader auflisten und alle abhängen
const detachAll = (gl, program) => {
const shaders = gl.getAttachedShaders(program) ?? [];
for (const shader of shaders) {
gl.detachShader(program, shader);
}
console.log(`${shaders.length} Shader abgehängt`);
return shaders;
};
detachAll(gl, program);
// Wichtig · Fallstricke
- Ist
shadernicht anprogramangehängt, erzeugt die Methode den Fehlergl.INVALID_OPERATION. Er wird nicht als Exception geworfen, sondern ist nur übergl.getError()abfragbar. - Rufe
detachShader()erst nach einem erfolgreichenlinkProgram()auf. Wenn du Shader vorher abhängst, fehlen sie beim Linken. Beim Debuggen hilft es außerdem, sie angehängt zu lassen, bis Fehlermeldungen gelesen wurden. - Einige ältere Treiber und Profiling-Werkzeuge (z. B. Spector.js) zeigen den Shader-Quelltext nicht mehr an, sobald die Shader abgehängt sind. Manche Engines verzichten deshalb im Debug-Modus auf das Abhängen.
- Bei verlorenem Kontext (
webglcontextlost) wird der Aufruf still ignoriert. - Kompatibilität: in allen Browsern mit WebGL-Unterstützung verfügbar, auch in
WebGL2RenderingContextundOffscreenCanvas-Kontexten.