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

WebGLRenderingContext.detachShader()

Methode

Entfernt einen zuvor mit <code>attachShader()</code> angehängten <code>WebGLShader</code> von einem <code>WebGLProgram</code>.

seit JavaScript WebGL 1.0 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.detachShader(program, shader)

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

Typ
void
Beschreibung
Kein 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);
2 Shader abgehängt

// Wichtig · Fallstricke

  • Ist shader nicht an program angehängt, erzeugt die Methode den Fehler gl.INVALID_OPERATION. Er wird nicht als Exception geworfen, sondern ist nur über gl.getError() abfragbar.
  • Rufe detachShader() erst nach einem erfolgreichen linkProgram() 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 WebGL2RenderingContext und OffscreenCanvas-Kontexten.