Signatur
Beschreibung
WebGL2RenderingContext ist die zweite Generation der WebGL-API. Einen solchen Kontext bekommt man über canvas.getContext("webgl2") (auch mit OffscreenCanvas in Web Workern). Er enthält alle Funktionen von WebGLRenderingContext (WebGL 1) und ergänzt sie um die Fähigkeiten von OpenGL ES 3.0. Shader werden in GLSL ES 3.00 geschrieben; die erste Zeile im Shader-Quelltext muss dann #version 300 es lauten.
Die wichtigsten Neuerungen gegenüber WebGL 1:
- Vertex Array Objects (
createVertexArray(),bindVertexArray()) sind fest eingebaut – die ErweiterungOES_vertex_array_objectentfällt. - Instanziertes Zeichnen mit
drawArraysInstanced(),drawElementsInstanced()undvertexAttribDivisor(). - Uniform Buffer Objects (
bindBufferBase(),getUniformBlockIndex(),uniformBlockBinding()). - 3D-Texturen und Textur-Arrays (
texImage3D(),texStorage2D()/texStorage3D()) sowie Sampler-Objekte (createSampler()). - Multiple Render Targets mit
drawBuffers(), Multisample-Renderbuffer (renderbufferStorageMultisample()) undblitFramebuffer(). - Transform Feedback, Query-Objekte (z. B. Occlusion Queries) und Sync-Objekte (
fenceSync(),clientWaitSync()). - Ganzzahlige Attribute und Uniforms, Texturen ohne Zweierpotenz-Größe ohne Einschränkungen bei Mipmaps und Wrapping, viele neue Texturformate.
Man nutzt WebGL 2 für anspruchsvolle 3D-Szenen, Datenvisualisierung, Spiele, Bildverarbeitung und GPU-Berechnungen. Viele Bibliotheken (z. B. Three.js, Babylon.js, PixiJS) verwenden WebGL 2 intern. Für neue Projekte mit Compute-Bedarf lohnt ein Blick auf WebGPU, WebGL 2 bleibt jedoch die am breitesten unterstützte GPU-API im Web.
Der Kontext ist zustandsbehaftet: Gebundene Puffer, Texturen, Programme und VAOs gelten global für alle folgenden Aufrufe. Fehler werden nicht als Ausnahmen geworfen, sondern über gl.getError() abgefragt.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $contextType Pflicht | string | Argument für canvas.getContext(): muss "webgl2" sein, um einen WebGL2RenderingContext zu erhalten. |
|
| $contextAttributes | WebGLContextAttributes | {} | Optionales Objekt, z. B. { alpha, antialias, depth, stencil, premultipliedAlpha, preserveDrawingBuffer, powerPreference, failIfMajorPerformanceCaveat, desynchronized }. |
Rückgabewert
getContext("webgl2") liefert den Kontext oder null, wenn WebGL 2 nicht verfügbar ist (fehlende Unterstützung, gesperrter Treiber, deaktivierte Hardwarebeschleunigung).Beispiele
Kontext anlegen mit Fallback auf WebGL 1
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2', { antialias: true })
?? canvas.getContext('webgl');
if (!gl) {
throw new Error('WebGL wird nicht unterstützt');
}
const isWebGL2 = gl instanceof WebGL2RenderingContext;
console.log('WebGL 2:', isWebGL2);
console.log(gl.getParameter(gl.VERSION));
gl.clearColor(0.1, 0.1, 0.15, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
Dreieck zeichnen mit GLSL ES 3.00 und Vertex Array Object
const gl = document.querySelector('canvas').getContext('webgl2');
const vsSource = `#version 300 es
in vec2 aPosition;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
}`;
const fsSource = `#version 300 es
precision highp float;
out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.5, 0.2, 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)) {
throw new Error(gl.getShaderInfoLog(shader));
}
return shader;
};
const program = gl.createProgram();
gl.attachShader(program, compile(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
// VAO speichert die komplette Attribut-Konfiguration
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.7, -0.7, -0.7, 0.7, -0.7]), gl.STATIC_DRAW);
const loc = gl.getAttribLocation(program, 'aPosition');
gl.enableVertexAttribArray(loc);
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(program);
gl.bindVertexArray(vao);
gl.drawArrays(gl.TRIANGLES, 0, 3);
Instanziertes Zeichnen: viele Objekte mit einem Draw-Call
// Annahme: program und vao aus dem vorigen Beispiel,
// der Vertex-Shader hat zusätzlich: in vec2 aOffset;
// und gl_Position = vec4(aPosition * 0.1 + aOffset, 0.0, 1.0);
const count = 100;
const offsets = new Float32Array(count * 2);
for (let i = 0; i < count; i++) {
offsets[i * 2] = Math.random() * 2 - 1;
offsets[i * 2 + 1] = Math.random() * 2 - 1;
}
gl.bindVertexArray(vao);
const offsetBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
const offsetLoc = gl.getAttribLocation(program, 'aOffset');
gl.enableVertexAttribArray(offsetLoc);
gl.vertexAttribPointer(offsetLoc, 2, gl.FLOAT, false, 0, 0);
gl.vertexAttribDivisor(offsetLoc, 1); // pro Instanz statt pro Vertex
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, count);
console.log(`${count} Dreiecke in einem Aufruf gezeichnet`);
Kontextverlust behandeln
const canvas = document.querySelector('canvas');
let gl = canvas.getContext('webgl2');
canvas.addEventListener('webglcontextlost', (event) => {
event.preventDefault(); // Wiederherstellung erlauben
console.warn('WebGL-Kontext verloren');
});
canvas.addEventListener('webglcontextrestored', () => {
console.log('Kontext wiederhergestellt – Ressourcen neu anlegen');
// Shader, Puffer und Texturen hier erneut erzeugen
});
// Zum Testen: Kontextverlust simulieren
const ext = gl.getExtension('WEBGL_lose_context');
ext?.loseContext();
setTimeout(() => ext?.restoreContext(), 1000);