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

WebGLRenderingContext.shaderSource()

Methode

Setzt den GLSL-Quellcode eines <code>WebGLShader</code>-Objekts. Danach wird der Shader mit <code>compileShader()</code> kompiliert.

seit JavaScript Baseline: alle Browser (WebGL 1.0) Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.shaderSource(shader, source)

Beschreibung

Mit shaderSource() übergeben Sie den GLSL-Quellcode (OpenGL ES Shading Language) als Zeichenkette an ein Shader-Objekt, das Sie vorher mit gl.createShader(gl.VERTEX_SHADER) oder gl.createShader(gl.FRAGMENT_SHADER) erzeugt haben. Das ist der erste Schritt der typischen Shader-Pipeline: erzeugen → Quelle setzen → kompilieren → an ein Programm anhängen → linken.

Die Methode prüft den Code nicht. Sie speichert ihn nur im Shader-Objekt. Syntaxfehler zeigen sich erst nach gl.compileShader(). Dann fragen Sie den Status mit gl.getShaderParameter(shader, gl.COMPILE_STATUS) ab und lesen die Fehlermeldung mit gl.getShaderInfoLog(shader).

Wenn Sie shaderSource() erneut aufrufen, wird die vorherige Quelle ersetzt. Ein bereits gelinktes Programm ändert sich dadurch nicht. Erst nach neuem Kompilieren und Linken wirkt der neue Code. Den aktuell gespeicherten Code können Sie mit gl.getShaderSource(shader) auslesen.

Parameter

Name Typ Default Beschreibung
$shader Pflicht WebGLShader Das Shader-Objekt, dessen Quellcode gesetzt werden soll. Es wird mit gl.createShader() erzeugt.
$source Pflicht string Der GLSL-Quellcode als Zeichenkette. Bei WebGL 2 muss #version 300 es ganz am Anfang stehen, ohne Leerzeile oder Leerzeichen davor.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Vertex- und Fragment-Shader kompilieren

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

const vertexSrc = `
  attribute vec2 aPosition;
  void main() {
    gl_Position = vec4(aPosition, 0.0, 1.0);
  }
`;

const fragmentSrc = `
  precision mediump float;
  void main() {
    gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0);
  }
`;

const compile = (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.VERTEX_SHADER, vertexSrc);
const fs = compile(gl.FRAGMENT_SHADER, fragmentSrc);

const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
console.log(gl.getProgramParameter(program, gl.LINK_STATUS));
true

Kompilierfehler sichtbar machen

const gl = document.createElement('canvas').getContext('webgl');
const shader = gl.createShader(gl.FRAGMENT_SHADER);

// Absichtlicher Fehler: fehlendes Semikolon
gl.shaderSource(shader, 'void main() { gl_FragColor = vec4(1.0) }');
gl.compileShader(shader);

console.log(gl.getShaderParameter(shader, gl.COMPILE_STATUS));
console.log(gl.getShaderInfoLog(shader));
false ERROR: 0:1: '}' : syntax error (Wortlaut je nach Browser/Treiber)

Shader-Quelle per fetch laden (WebGL 2)

const gl = document.querySelector('canvas').getContext('webgl2');

const loadShader = async (url, type) => {
  const res = await fetch(url);
  const source = (await res.text()).trimStart(); // #version muss am Anfang stehen
  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 = await loadShader('/shaders/basic.vert', gl.VERTEX_SHADER);
console.log(gl.getShaderSource(vs).split('\n')[0]);
#version 300 es

// Wichtig · Fallstricke

  • Keine Fehlerprüfung: shaderSource() meldet keine Syntaxfehler. Prüfen Sie immer COMPILE_STATUS nach compileShader(). Sonst schlägt das Programm stillschweigend fehl.
  • WebGL 2 / GLSL ES 3.00: Die Zeile #version 300 es muss das allererste Zeichen der Quelle sein. Template-Literale beginnen oft mit einem Zeilenumbruch. Verwenden Sie deshalb .trim() oder schreiben Sie die Direktive direkt nach dem Backtick.
  • Zeichensatz: GLSL ES erlaubt nur einen eingeschränkten ASCII-Zeichensatz. Umlaute oder andere Nicht-ASCII-Zeichen, selbst in Kommentaren, können in älteren Implementierungen Fehler auslösen.
  • Ist shader kein gültiges Shader-Objekt oder wurde es schon gelöscht, entsteht der Fehler INVALID_VALUE bzw. INVALID_OPERATION. Diesen fragen Sie mit gl.getError() ab.
  • Geht der Kontext verloren (webglcontextlost), müssen alle Shader neu erzeugt werden, einschließlich shaderSource().
  • Sicherheit: Laden Sie Shader-Code nicht ungeprüft aus fremden Quellen. Fehlerhafte oder sehr aufwendige Shader können die GPU blockieren und die Seite einfrieren lassen.
  • Unterstützt in allen modernen Browsern. In WebGL2RenderingContext ist die Methode identisch vorhanden.