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

WebGLRenderingContext.getAttachedShaders()

Methode

Gibt ein Array aller <code>WebGLShader</code>-Objekte zurück, die aktuell an das übergebene <code>WebGLProgram</code> angehängt sind.

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

Signatur

WebGLRenderingContext.prototype.getAttachedShaders(program)

Beschreibung

Mit getAttachedShaders() fragst du ab, welche Shader-Objekte gerade per attachShader() an ein Programm gebunden sind. Typischerweise sind das ein Vertex- und ein Fragment-Shader. Die Methode entspricht dem OpenGL-ES-Aufruf glGetAttachedShaders.

Nützlich ist sie vor allem zum Debuggen, zum Aufräumen (alle Shader eines Programms lösen und löschen, bevor das Programm selbst gelöscht wird) und für Werkzeuge, die zur Laufzeit ein Programm untersuchen, etwa um Shader-Quelltexte mit getShaderSource() auszulesen oder einzelne Shader beim Hot-Reload auszutauschen.

Die Methode gibt es auch auf WebGL2RenderingContext, das Verhalten ist dort identisch. Die Reihenfolge der Shader im Array ist nicht festgelegt. Den Typ eines Shaders findest du daher über gl.getShaderParameter(shader, gl.SHADER_TYPE) heraus.

Parameter

Name Typ Default Beschreibung
$program Pflicht WebGLProgram Das Programm, dessen angehängte Shader abgefragt werden sollen.

Rückgabewert

Typ
WebGLShader[] | null
Beschreibung
Ein Array mit den angehängten WebGLShader-Objekten, oder ein leeres Array, wenn keine Shader angehängt sind. Ist der Kontext verloren (context lost) oder tritt ein Fehler auf, wird null zurückgegeben.

Beispiele

Angehängte Shader eines Programms auflisten

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);
  return shader;
};

const vs = compile(gl.VERTEX_SHADER, 'attribute vec4 p; void main(){ gl_Position = p; }');
const fs = compile(gl.FRAGMENT_SHADER, 'precision mediump float; void main(){ gl_FragColor = vec4(1.0); }');

const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);

const shaders = gl.getAttachedShaders(program);
console.log(shaders.length);
shaders.forEach((s) => {
  const type = gl.getShaderParameter(s, gl.SHADER_TYPE);
  console.log(type === gl.VERTEX_SHADER ? 'Vertex' : 'Fragment');
});
2 Vertex Fragment

Programm samt Shadern sauber freigeben

const destroyProgram = (gl, program) => {
  const shaders = gl.getAttachedShaders(program) ?? [];
  for (const shader of shaders) {
    gl.detachShader(program, shader);
    gl.deleteShader(shader);
  }
  gl.deleteProgram(program);
};

// Aufruf, z. B. beim Verlassen einer Szene
destroyProgram(gl, program);
console.log(gl.isProgram(program));
false

Fragment-Shader beim Hot-Reload austauschen

const replaceFragmentShader = (gl, program, newSource) => {
  const old = (gl.getAttachedShaders(program) ?? [])
    .find((s) => gl.getShaderParameter(s, gl.SHADER_TYPE) === gl.FRAGMENT_SHADER);

  const fresh = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fresh, newSource);
  gl.compileShader(fresh);
  if (!gl.getShaderParameter(fresh, gl.COMPILE_STATUS)) {
    console.error(gl.getShaderInfoLog(fresh));
    gl.deleteShader(fresh);
    return false;
  }

  if (old) {
    gl.detachShader(program, old);
    gl.deleteShader(old);
  }
  gl.attachShader(program, fresh);
  gl.linkProgram(program);
  return gl.getProgramParameter(program, gl.LINK_STATUS);
};

console.log(replaceFragmentShader(gl, program,
  'precision mediump float; void main(){ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }'));
true

// Wichtig · Fallstricke

  • Rückgabewert null: Wenn der Kontext verloren ist (webglcontextlost) oder das Argument ungültig ist, gibt die Methode null statt eines Arrays zurück. Prüfe darauf, z. B. mit ?? [].
  • Ungültiges Argument: Ist program kein WebGLProgram oder wurde es schon gelöscht, entsteht INVALID_VALUE (abfragbar mit gl.getError()). Programme aus einem anderen Kontext führen zu INVALID_OPERATION.
  • Keine feste Reihenfolge: Verlass dich nicht auf die Position im Array. Den Typ bestimmst du immer mit SHADER_TYPE.
  • Löschen ohne Lösen: Ein Shader, der mit deleteShader() gelöscht, aber nicht gelöst wurde, bleibt angehängt und taucht weiter im Ergebnis auf, bis detachShader() aufgerufen oder das Programm gelöscht wird.
  • Die Methode steht in allen modernen Browsern mit WebGL-Unterstützung zur Verfügung, ebenso auf WebGL2RenderingContext.