Diese Serie beschäftigt sich mit der Darstellung von 3D-Inhalten auf Websites und den notwendigen APIs und Tools die dafür genutzt werden können.
Es wird im ersten Teil um das Setup und das Rendern einer einfachen Geometrie gehen. In den folgenden Artikeln wird ein eigenes 3D-Objekt importiert, und die Interaktion mit der Szene implementiert.
WebGL (Web Graphics Library) ist ein plattformübergreifender Standard für das Rendern von interaktiven 2D- und 3D-Grafiken im Netz. Die WebGL API bietet die Möglichkeit via JavaScript 3D-Grafiken über das HTML <canvas> Element darzustellen. Da die Schnittstelle Zugriff auf die *shader language* der OpenGL ES (Open Graphics Library for Embedded Systems) hat, werden die Grafiken von der GPU berechnet.
Mit reinem WebGL interaktive Applikationen zu erstellen ist mühsam und umständlich, es existieren frameworks mit denen die Umsetzung vereinfacht wird. Die Bekanntesten dürften wohl THREE.js und Babylon.js sein, wobei der Fokus von Babylon.js auf dem Erstellen von Spielen liegt und THREE.js einen eher unvoreingenommen Ansatz hat. In dieser Serie wird THREE.js eingesetzt.
Als Grundlage zur Darstellung von WebGL-Inhalten wird das HTML <canvas> Element und ein *rendering context* benötigt. Im script tag wird THREE.js in das Dokument eingebunden, danach die Datei main.js, die unseren Code beinhalten wird.
<body>
<script src="src/js/three.js"></script>
<script src="src/js/main.js"></script>
</body>
Es werden drei Komponenten benötigt, um etwas darzustellen:
- eine Szene
- eine Kamera
- der WebGL Renderer (rendering context)
Diese werden in main.js wie folgt angelegt:
/* main.js */
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75, // FOV (field of view) in Grad
window.innerWidth / window.innerHeight, // Verhältnis des render context
0.1, // near - Objekte mit einer kleineren Distanz als dieser Wert werden nicht angezeigt
1000 // far - Objekte mit einer größeren Distanz als dieser Wert werden nicht angezeigt
);
const renderer = new THREE.WebGLRenderer(); // ein von THREE.js erzeugtes Element
renderer.setSize(window.innerWidth, window.innerHeight); // Größe des Canvas
document.body.appendChild(renderer.domElement);
Um etwas dargestellt zu bekommen, kann eine der in THREE.js enthaltenen Geometrie-Klassen instanziiert werden.
const geometry = new THREE.TorusKnotGeometry(13, 2.5, 250, 10, 9, 6);
const material = new THREE.MeshBasicMaterial({ color: 0xe6db74 });
const torus = new THREE.Mesh(geometry, material);
scene.add(torus); // Der Torus wird zur Szene hinzugefügt
// Damit das noch etwas besser aussieht wird ein wireframe auf den Torus gelegt
const wireframe = new THREE.WireframeGeometry(geometry);
const line = new THREE.LineSegments(wireframe);
line.material.depthTest = false;
line.material.opacity = 0.25;
line.material.color = new THREE.Color("#000");
line.material.transparent = true;
scene.add(line);
camera.position.z = 70; // Die Position der Kamera muss angepasst werden, damit die Objekte zu sehen sind
```javascript
Jetzt fehlt noch der render loop, eine rekursive Funktion die requestAnimationFrame aufruft. Diese wird aufgerufen, um dem Browser mitzuteilen, dass er einen Repaint durchführen soll - ergo der nächste Frame gerendert wird. Ein typischer Wert für diese frame rate ist 60 Mal pro Sekunde. Damit das Objekt rotiert, wird der Rotations-Wert für die X und Y-Achse bei jedem Aufruf der draw() Funktion inkrementiert.
const meshes = [torus, line]
function draw() {
requestAnimationFrame(draw);
meshes.forEach(element => {
element.rotation.x += 0.001;
element.rotation.y += 0.001;
});
renderer.render(scene, camera);
}
draw();
Das Ergebnis sieht jetzt so aus: