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

WebGLRenderingContext.createShader()

Methode

Erzeugt ein leeres <code>WebGLShader</code>-Objekt (Vertex- oder Fragment-Shader), das danach mit <code>shaderSource()</code> befüllt und mit <code>compileShader()</code> kompiliert wird.

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

Signatur

WebGLRenderingContext.prototype.createShader(type)

Beschreibung

createShader() ist der erste Schritt jeder WebGL-Shader-Pipeline. Die Methode legt auf der GPU-Seite ein neues, noch leeres Shader-Objekt an. Anschließend übergibt man den GLSL-Quelltext mit gl.shaderSource(), kompiliert ihn mit gl.compileShader() und hängt den fertigen Shader per gl.attachShader() an ein WebGLProgram.

Ein lauffähiges Programm braucht immer genau einen Vertex-Shader (gl.VERTEX_SHADER), der die Positionen der Eckpunkte berechnet, und einen Fragment-Shader (gl.FRAGMENT_SHADER), der die Farbe jedes Pixels bestimmt. Beide werden jeweils mit einem eigenen createShader()-Aufruf erzeugt.

Wichtig: createShader() selbst prüft keinen Quelltext. Ob die Kompilierung erfolgreich war, muss man nach compileShader() explizit mit gl.getShaderParameter(shader, gl.COMPILE_STATUS) abfragen; Fehlermeldungen liefert gl.getShaderInfoLog(). Die Methode steht identisch auch in WebGL2RenderingContext zur Verfügung.

Parameter

Name Typ Default Beschreibung
$type Pflicht GLenum (number) Art des Shaders: gl.VERTEX_SHADER (35633) oder gl.FRAGMENT_SHADER (35632). Andere Werte erzeugen den Fehler gl.INVALID_ENUM.

Rückgabewert

Typ
WebGLShader | null
Beschreibung
Ein neues, leeres WebGLShader-Objekt. Bei ungültigem type oder verlorenem Kontext (webglcontextlost) wird null zurückgegeben.

Beispiele

Vertex- und Fragment-Shader anlegen

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

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

console.log(vertexShader instanceof WebGLShader);
console.log(gl.getShaderParameter(vertexShader, gl.SHADER_TYPE) === gl.VERTEX_SHADER);
true true

Wiederverwendbare Hilfsfunktion mit Fehlerprüfung

const compileShader = (gl, type, source) => {
  const shader = gl.createShader(type);
  if (!shader) throw new Error('Shader konnte nicht erzeugt werden (Kontext verloren?)');

  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(`Kompilierfehler: ${log}`);
  }
  return shader;
};

const gl = document.querySelector('canvas').getContext('webgl');
const vs = compileShader(gl, gl.VERTEX_SHADER, `
  attribute vec2 aPosition;
  void main() {
    gl_Position = vec4(aPosition, 0.0, 1.0);
  }
`);
console.log('Vertex-Shader kompiliert:', vs);
Vertex-Shader kompiliert: WebGLShader {}

Komplettes Programm bauen und Dreieck zeichnen

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

const make = (type, src) => {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(s));
  return s;
};

const vs = make(gl.VERTEX_SHADER, `attribute vec2 p; void main(){ gl_Position = vec4(p, 0.0, 1.0); }`);
const fs = make(gl.FRAGMENT_SHADER, `precision mediump float; void main(){ gl_FragColor = vec4(1.0, 0.4, 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));

// Shader werden nach dem Linken nicht mehr benötigt
gl.deleteShader(vs);
gl.deleteShader(fs);

gl.useProgram(program);
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.8, -0.8, -0.8, 0.8, -0.8]), gl.STATIC_DRAW);
const loc = gl.getAttribLocation(program, 'p');
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
(Ein oranges Dreieck wird auf das Canvas gezeichnet.)

// Wichtig · Fallstricke

  • Kein automatischer Fehler: Syntaxfehler im GLSL-Code werfen keine JavaScript-Exception. Immer COMPILE_STATUS prüfen und getShaderInfoLog() auslesen.
  • Kontextverlust: Geht der WebGL-Kontext verloren (z. B. GPU-Reset, Tab im Hintergrund auf Mobilgeräten), liefert createShader() null. Nach webglcontextrestored müssen alle Shader neu erzeugt werden.
  • Speicher freigeben: Shader belegen GPU-Ressourcen. Nach erfolgreichem linkProgram() können sie mit gl.deleteShader() markiert werden; sie werden gelöscht, sobald sie von keinem Programm mehr referenziert sind.
  • GLSL-Version: In WebGL 1 wird GLSL ES 1.00 verwendet; für GLSL ES 3.00 (#version 300 es, muss die allererste Zeile sein) ist ein webgl2-Kontext nötig.
  • Präzision: Fragment-Shader in WebGL 1 benötigen eine Präzisionsangabe wie precision mediump float;, sonst schlägt die Kompilierung fehl.
  • Kompatibilität: in allen aktuellen Browsern unterstützt; auch in Web Workern über OffscreenCanvas verfügbar.