Vom Grafiktreiber bis zum HTML-Tag

🧰Technologien für 3D im Web

3D im Browser ist ein Schichtenmodell: ganz unten die GPU-Schnittstellen WebGL und WebGPU, darüber Bibliotheken wie three.js oder Babylon.js, ganz oben Komfort-Komponenten wie <model-viewer>. Das Dateiformat glTF verbindet alle Schichten.

🏗️ Die Schichten

glTF / GLBDateiformatTransportformat für Modelle, von allen Schichten darüber verstanden
<model-viewer>Web-Komponenteein HTML-Tag für ein Modell – Drehen, Zoomen, AR; intern three.js
three.js · Babylon.jsEngine / BibliothekSzenengraph, Materialien, Loader, Kamera-Steuerung, Renderer für WebGL und WebGPU
WebGL 1 / 2GPU-APIOpenGL ES 2.0 / 3.0 im Browser, GLSL-Shader, Zustandsautomat
WebGPUGPU-APImoderne, explizite API (wie Vulkan/Metal/D3D12), WGSL-Shader, Compute
Browser → Grafiktreiber (oft über ANGLE auf Direct3D/Metal/Vulkan übersetzt) → GPU

⚖️ WebGL 1, WebGL 2 und WebGPU

WebGL 1WebGL 2WebGPU
GrundlageOpenGL ES 2.0OpenGL ES 3.0Vulkan / Metal / Direct3D 12
SpezifikationKhronos, 2011Khronos, 2017W3C, seit 2023 in Chrome
Shader-SpracheGLSL ES 1.00GLSL ES 3.00WGSL
InstancingErweiterung (ANGLE_instanced_arrays)eingebauteingebaut
Vertex Array ObjectsErweiterung (OES_vertex_array_object)eingebautPipeline-Objekte
Multisample-Renderzieleneinja (renderbufferStorageMultisample)ja
Compute-Shaderneinneinja
Programmiermodellglobaler Zustandsautomat, jeder Aufruf sofortwie WebGL 1vorab gebaute Pipelines, Befehle werden aufgezeichnet und gesammelt abgeschickt
Dein Browser – live geprüft
prüfe …
WebGPU-Dreieck (Code unten)

🔺 Rohes WebGL 2: ein Dreieck

Rund 20 Zeilen für ein einfarbiges Dreieck – ohne Matrizen, Licht oder Textur. Das Labor zeigt die ausgebaute Fassung.

1const gl = canvas.getContext("webgl2");
2const vs = `#version 300 es
3in vec2 aPos;
4void main() { gl_Position = vec4(aPos, 0.0, 1.0); }`;
5const fs = `#version 300 es
6precision mediump float;
7out vec4 color;
8void main() { color = vec4(0.08, 0.72, 0.65, 1.0); }`;
9const prog = gl.createProgram();
10for (const [type, src] of [[gl.VERTEX_SHADER, vs], [gl.FRAGMENT_SHADER, fs]]) {
11 const s = gl.createShader(type);
12 gl.shaderSource(s, src); gl.compileShader(s); gl.attachShader(prog, s);
13}
14gl.linkProgram(prog); gl.useProgram(prog);
15gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
16gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.6, -0.6, -0.5, 0.6, -0.5]), gl.STATIC_DRAW);
17const loc = gl.getAttribLocation(prog, "aPos");
18gl.enableVertexAttribArray(loc);
19gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
20gl.clearColor(0.06, 0.09, 0.16, 1); gl.clear(gl.COLOR_BUFFER_BIT);
21gl.drawArrays(gl.TRIANGLES, 0, 3); // der Draw Call
🎛️ Zum WebGL-Labor

🟣 WebGPU: dasselbe Dreieck

Mehr Vorbereitung, dafür weniger Überraschungen zur Laufzeit: Der komplette Zustand steckt in der Pipeline, Befehle werden gesammelt abgeschickt. Dieser Code läuft oben live, wenn dein Browser WebGPU kann.

1const adapter = await navigator.gpu.requestAdapter();
2const device = await adapter.requestDevice();
3const context = canvas.getContext("webgpu");
4const format = navigator.gpu.getPreferredCanvasFormat();
5context.configure({ device, format });
6
7// Shader in WGSL statt GLSL – Vertex- und Fragment-Stufe in einem Modul
8const module = device.createShaderModule({ code: `
9 @vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
10 var p = array(vec2f(0.0, 0.6), vec2f(-0.6, -0.5), vec2f(0.6, -0.5));
11 return vec4f(p[i], 0.0, 1.0);
12 }
13 @fragment fn fs() -> @location(0) vec4f {
14 return vec4f(0.08, 0.72, 0.65, 1.0);
15 }` });
16
17// Der gesamte Zustand wird vorab in einer unveränderlichen Pipeline festgelegt
18const pipeline = device.createRenderPipeline({
19 layout: "auto",
20 vertex: { module, entryPoint: "vs" },
21 fragment: { module, entryPoint: "fs", targets: [{ format }] },
22});
23
24// Befehle aufzeichnen und gesammelt an die GPU-Warteschlange schicken
25const encoder = device.createCommandEncoder();
26const pass = encoder.beginRenderPass({ colorAttachments: [{
27 view: context.getCurrentTexture().createView(),
28 clearValue: { r: 0.06, g: 0.09, b: 0.16, a: 1 },
29 loadOp: "clear", storeOp: "store",
30}] });
31pass.setPipeline(pipeline);
32pass.draw(3); // 3 Vertices, keine Puffer nötig
33pass.end();
34device.queue.submit([encoder.finish()]);

🧊 three.js

Die verbreitetste 3D-Bibliothek im Web (seit 2010, MIT-Lizenz, Ricardo Cabello „mrdoob“). Schlank, modular, riesige Beispielsammlung. Hier installiert: r186. Diese App nutzt sie für die Ferienwohnung.

1import * as THREE from "three";
2import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
3import { OrbitControls } from "three/addons/controls/OrbitControls.js";
4
5const renderer = new THREE.WebGLRenderer({ antialias: true });
6document.body.appendChild(renderer.domElement);
7const scene = new THREE.Scene();
8const camera = new THREE.PerspectiveCamera(30, innerWidth / innerHeight, 0.1, 2000);
9camera.position.set(14.5, 25.5, 19.5);
10new OrbitControls(camera, renderer.domElement);
11scene.add(new THREE.HemisphereLight(0xbcd3e8, 0x3b3a35, 2));
12const gltf = await new GLTFLoader().loadAsync("/modelle/apartment.glb");
13scene.add(gltf.scene);
14renderer.setAnimationLoop(() => renderer.render(scene, camera));
🧊 Three.js ausführlich erklärt

🪐 Babylon.js

Vollständige Engine von Microsoft (seit 2013, Apache-2.0, in TypeScript geschrieben): Physik, GUI, Inspector, Node-Material-Editor, WebXR. Mehr „Spiele-Engine“, dafür größer. Gleiches Modell, gleiche Idee:

1import { Engine, Scene, ArcRotateCamera, HemisphericLight, SceneLoader, Vector3 } from "@babylonjs/core";
2import "@babylonjs/loaders/glTF"; // registriert den glTF-Loader
3
4const engine = new Engine(canvas, true); // true = Anti-Aliasing
5const scene = new Scene(engine);
6const camera = new ArcRotateCamera("kamera", Math.PI / 4, Math.PI / 3, 40, Vector3.Zero(), scene);
7camera.attachControl(canvas, true); // Maus/Touch wie OrbitControls
8new HemisphericLight("licht", new Vector3(0, 1, 0), scene);
9await SceneLoader.AppendAsync("/modelle/", "apartment.glb", scene);
10engine.runRenderLoop(() => scene.render());

🧩 <model-viewer>

Web-Komponente von Google: ein HTML-Tag, fertig. Drehen, Zoomen, Schatten, Umgebungslicht und AR (WebXR, Scene Viewer auf Android, Quick Look auf iOS) – ohne eine Zeile JavaScript. Ideal für Produktseiten.

1<!-- npm install @google/model-viewer, dann: import "@google/model-viewer"; -->
2<model-viewer
3 src="/modelle/apartment.glb"
4 alt="Ferienwohnung in 3D"
5 camera-controls
6 auto-rotate
7 shadow-intensity="1"
8 ar>
9</model-viewer>
Für die Ferienwohnung wäre das die kürzeste Lösung – aber ohne Explosionsdarstellung, Ebenen und eigene Kamerafahrten. Dafür braucht es three.js.

🧭 Was nehme ich wann?

Ein Modell auf einer Produktseite zeigen
<model-viewer>
Ein Tag, AR inklusive, keine 3D-Kenntnisse nötig.
Eigene interaktive Szene, Konfigurator, Visualisierung
three.js
Volle Kontrolle, kleine Bundles, riesige Community.
Spiel oder Anwendung mit Physik, GUI, Editor
Babylon.js
Alles aus einer Hand, starke Werkzeuge.
Lernen, Spezialeffekte, maximale Performance
WebGL / WebGPU direkt
Man versteht jede Zeile – und schreibt jede Zeile selbst. WebGPU zusätzlich für Compute.