It’s #FrontendFriday – 3D Anwendungen im Browser mit Three.js entwickeln

21.10.2022

Liebe #FrontendFriday Freunde, heute möchte ich euch einmal die Möglichkeiten des dreidimensionalen im Browser etwas näherbringen. Dazu werfen wir gemeinsam einen Blick auf die JavaScript-Bibliothek Three.js.

Einführung

Wer schonmal vor dem Problem Stand 3D-Anwendungen im Web zu realisieren oder coole Webseiten mit 3D Anteilen erstellen zu wollen, weiß um die Schwierigkeiten. Seit einigen Jahren bieten Browser die Möglichkeit, über WebGL direkt auf die Grafikhardware des Computers zuzugreifen, um so auch komplexe 3D Anwendungen im Browser darzustellen. Problem hierbei ist, dass die Schnittstelle sehr Low-Level ist und man sich gut mit Grafikprogrammierung auskennen sollte. An dieser Stelle kommt Three.js ins Spiel. Die Bibliothek setzt direkt über WebGL an, und hilft uns dabei diese Arbeit einfacher zu machen.

Direkt auf der Three.js Startseite sind viele interessante Projekte und Webseiten verlinkt welche die Möglichkeiten der Bibliothek aufzeigen. Von Spielen über Animationen und Produktdarstellungen sind der Kreativität keine Grenzen gesetzt.

Ein Beispiel

Im Folgenden will ich euch ein kleines Beispiel zeigen, was man hiermit entwickeln kann. Dazu habe ich mich von Alexander Grünwald und Let it Snow mit SASS etwas inspirieren lassen und zeige euch wie wir es im 3 dimensionalen Raum schneien lassen können, auch wenn es (wahrscheinlich) noch etwas dauert bis zum ersten Schnee.

Das Beispiel findet ihr hier Webseite und den Code dazu gibt es hier Repository. Um zu starten brauchen wir eine index.html und eine index.js und die Three.js Bibliothek.

 

Three.js Standardsetup

Unsere index.html sieht wie folgt aus:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Snowfall</title>
        <style>
            body { margin: 0; }
        </style>
    </head>
    <body>
        <script type="module" src="three.js"></script>
        <script type="module" src="index.js"></script>
    </body>
</html>

Hier ist es wichtig alle three.js module vor den eigenen Javascript files zu laden. Danach können wir direkt zum Grafikteil übergehen in unserer index.js importieren wir alles aus der Three-Bibliothek und erstellen als Erstes eine Szene. Diese Szene hält alle unsere Objekte in dieser 3D Welt. Im Anschluss brauchen wir eine Kamera. Diese legt fest, welchen Bereich der Szene wir sehen, wie nah wir an Objekten dran sind usw. Um die Szene und die Kamera zu kombinieren, benötigen wir einen Renderer, dieser ist das Hauptstück einer 3D Anwendung und führt beides zusammen und gibt es auf unserem Bildschirm aus. Diesen setzen wir auf die volle Fenster Breite und Höhe sowie auf eine bestimmte Hintergrundfarbe und hängen ihn letztlich an unser html Dokument an.

import * as THREE from 'three.js'

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 20;

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0x020824);

document.body.appendChild( renderer.domElement );

 

Die Schneeflocken

Um unsere Schneeflocken zu erstellen, benutze ich an dieser Stelle eine vereinfachte Version ohne Textur:

// Create Snowflakes			
const geometry = new THREE.BufferGeometry();
const vertices = [], velocities = [] , materials = [] , maxRange=500, minRange =150, maxHeight = 300;
let particles;
//Spawn Snowflakes at Random positions with random velocity(fallspeed)
for ( let i = 0; i < 10000; i ++ ) {

    vertices.push(
        Math.floor(Math.random() * maxRange - minRange),
        Math.floor(Math.random() * maxHeight),
        Math.floor(Math.random() * maxRange - minRange)
    );

	velocities.push(
		Math.floor(Math.random() * 2) * 0.15,
		Math.floor(Math.random() * 3) * 0.2,
		Math.floor(Math.random() * 1.5) * 0.1
	);

}

geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'velocity', new THREE.Float32BufferAttribute( velocities, 3) );

//Add all Particles to the Scene
materials[ 0 ] = new THREE.PointsMaterial( { size: 0.3, color: 0xFFFFFF, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );

particles = new THREE.Points( geometry, materials[ 0 ] );
scene.add( particles );

Hier wird eine einfache Geometrie benutzt und an zufälliger Stelle im Raum erstellt. Unsere Flocken brauchen zusätzlich auch noch eine Fallgeschwindigkeit, dafür ist der Wert in velocities. Damit die Geometrie sichtbar wird müssen wir ihr ein Material zuordnen, welches hier ganz einfach gehalten ein weißes Rechteck der Größe 0.3 ist. Das ganze fassen wir als Punktearray zusammen und fügen es unserer Szene hinzu, was dann so aussieht:

Punktearray an zufälliger Stelle im Raum

 

Die Schneeflocken animieren

Als letztes müssen wir die Schneeflocken noch animieren:

const particlePositionArray = particles.geometry.attributes.position.array;
const particleVelocityArray = particles.geometry.attributes.velocity.array;
//For Updates in the Scene e.g. the falling snow needs to be updated
function animate() {
    requestAnimationFrame( animate );
    updateParticles();
    renderer.render( scene, camera );
};

//Calculates the snowfall for every particle
function updateParticles(){
	for (let i = 0; i < 10000 * 3; i += 3){
		particlePositionArray[i] -= particleVelocityArray[i];
		particlePositionArray[i+1] -= particleVelocityArray[i+1];
		particlePositionArray[i+2] -= particleVelocityArray[i+2];

		if(particlePositionArray[i+1] < -200){
			particlePositionArray[i] = Math.floor(Math.random() * maxRange - minRange);
			particlePositionArray[i+1] = Math.floor(Math.random() * maxHeight);
			particlePositionArray[i+2] = Math.floor(Math.random() * maxRange - minRange);
		}
	}

	particles.geometry.attributes.position.needsUpdate = true;
}

animate();

In einer animate() Funktion wird unsere Szene geupdated, so zum Beispiel auch die Schneeflocken. Dafür gehen wir über alle Flocken in einer Schleife und verändern ihre Position um den Wert Velocity (unsere Fallgeschwindigkeit) und ab einer bestimmten Höhe werden die Flocken wieder zufällig zurückgesetzt, sodass wir ein endloses Schneegestöber haben.

Auf der oben verlinkten Seite, habe ich noch ein paar Modelle in die Szene eingefügt und etwas Licht damit es interessanter aussieht.

 

Wer also schöne 3D Inhalte für das Web erstellen will, kann sich gerne einmal Three.js anschauen. Der Start setzt ein paar 3D Kenntnisse voraus, ansonsten ist die Bibliothek aber ein mächtiges Werkzeug, um anspruchsvolle 3D Anwendungen im Browser zu erstellen.

Bis zum nächsten #FrontendFriday :)

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*Pflichtfelder

*