Bevor ich Webentwickler wurde, arbeitete ich in der VFX-Branche und erstellte preisgekrönte, High-End-3D-Effekte für Filme und Fernsehserien wie Tron, The Thing, Resident Evil und Vikings. Um diese Effekte erstellen zu können, mussten wir hoch entwickelte Animationssoftware wie Maya, 3Ds Max oder Houdini verwenden und lange Stunden mit Offline-Rendering auf Render Farms verbringen, die aus Hunderten von Maschinen bestanden. Da ich so lange mit diesen Werkzeugen gearbeitet habe, bin ich vom aktuellen Stand der Webtechnologie erstaunt. Wir können jetzt qualitativ hochwertige 3D-Inhalte direkt im Webbrowser in Echtzeit mit WebGL und Three.js erstellen und anzeigen.
Hier ist ein Beispiel für ein Projekt, das mit diesen Technologien erstellt wurde. Weitere Projekte, die three.js verwenden, finden Sie auf deren Website.

Wie die Beispiele auf der Three.js-Website zeigen, haben 3D-Visualisierungen ein riesiges Potenzial in den Bereichen E-Commerce, Einzelhandel, Unterhaltung und Werbung.
WebGL ist eine Low-Level-JavaScript-API, die die Erstellung und Anzeige von 3D-Inhalten im Browser über die GPU ermöglicht. Da WebGL eine Low-Level-API ist, kann sie leider etwas schwierig und mühsam zu verwenden sein. Sie müssen Hunderte von Codezeilen schreiben, um selbst die einfachsten Aufgaben auszuführen. Three.js hingegen ist eine Open-Source-JavaScript-Bibliothek, die die Komplexität von WebGL abstrahiert und es Ihnen ermöglicht, 3D-Inhalte in Echtzeit auf wesentlich einfachere Weise zu erstellen.
In diesem Tutorial stelle ich die Grundlagen der Three.js-Bibliothek vor. Es ist sinnvoll, mit einem einfachen Beispiel zu beginnen, um die Grundlagen besser zu vermitteln, wenn eine neue Programmierbibliothek eingeführt wird, aber ich möchte noch einen Schritt weiter gehen. Ich werde auch versuchen, eine Szene zu erstellen, die ästhetisch ansprechend und sogar bis zu einem gewissen Grad fotorealistisch ist.
Wir beginnen nur mit einer einfachen Ebene und einer Kugel, aber am Ende wird es so aussehen:
Siehe den Pen learning-threejs-final von Engin Arslan (@enginarslan) auf CodePen.
Fotorealismus ist der Gipfel der Computergrafik, aber die Erreichung hängt nicht unbedingt von der verfügbaren Rechenleistung ab, sondern von einem klugen Einsatz von Techniken aus Ihrem Werkzeugkasten. Hier sind einige Techniken, die Sie in diesem Tutorial kennenlernen werden und die Ihren Szenen helfen werden, Fotorealismus zu erreichen.
- Farb-, Bump- und Rauheitskarten.
- Physikalisch basierte Materialien.
- Beleuchtung mit Schatten.

Die grundlegenden 3D-Prinzipien und -Techniken, die Sie hier lernen werden, sind in jeder anderen Umgebung zur Erstellung von 3D-Inhalten relevant, sei es Blender, Unity, Maya oder 3Ds Max.
Dies wird ein langes Tutorial. Wenn Sie eher ein Video-Typ sind oder mehr über die Fähigkeiten von Three.js erfahren möchten, sollten Sie mein Video-Training zu diesem Thema auf Lynda.com ansehen.
Anforderungen
Bei der Verwendung von Three.js ist es hilfreich, wenn Sie lokal arbeiten, die HTML-Datei über einen lokalen Server zu servieren, um Szenen-Assets wie externe 3D-Geometrien, Bilder usw. laden zu können. Wenn Sie nach einem einfach einzurichtenden Server suchen, können Sie Python verwenden, um einen einfachen HTTP-Server zu starten. Python ist auf vielen Betriebssystemen vorinstalliert.
Sie müssen sich jedoch keine Gedanken über die Einrichtung eines lokalen Entwicklungsservers machen, um diesem Tutorial zu folgen. Sie werden stattdessen auf Daten-URLs zurückgreifen, um Assets wie Bilder zu laden und den Overhead der Server-Einrichtung zu vermeiden. Mit dieser Methode können Sie Ihre Three.js-Szene problemlos in Online-Code-Editoren wie CodePen ausführen.
Dieses Tutorial setzt Grundkenntnisse in JavaScript (grundlegend bis fortgeschritten) und ein gewisses Verständnis der Frontend-Webentwicklung voraus. Wenn Sie sich mit JavaScript nicht wohlfühlen, aber auf einfache Weise damit beginnen möchten, könnten Sie den Kurs/das Buch „Coding for Visual Learners: Learning JavaScript with p5.js“ in Betracht ziehen. (Haftungsausschluss: Ich bin der Autor)
Lassen Sie uns mit dem Erstellen von 3D-Grafiken im Web beginnen!
Erste Schritte
Ich habe bereits einen Pen vorbereitet, mit dem Sie dieses Tutorial verfolgen können.
Der zu verwendende HTML-Code ist denkbar einfach. Er benötigt nur ein div-Element, das die Leinwand hostet, auf der die 3D-Grafiken angezeigt werden. Außerdem wird die Three.js-Bibliothek (Version 86) von einem CDN geladen.
<div id="webgl"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js"></script>
Codepen blendet aus Bequemlichkeit einige der aktuell vorhandenen HTML-Strukturen aus. Wenn Sie diese Szene in anderen Online-Editoren oder lokal erstellen würden, müsste Ihr HTML etwas Ähnliches wie den folgenden Code enthalten, wobei main.js die Datei wäre, die den JavaScript-Code enthält.
<!DOCTYPE html>
<html>
<head>
<title>Three.js</title>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="webgl"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js"></script>
<script src="./main.js"></script>
</body>
</html>
Beachten Sie die einfache CSS-Deklaration innerhalb des HTML. Dies wäre das, was Sie im CSS-Tab von Codepen hätten.
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
Dies dient dazu, sicherzustellen, dass keine Abstände oder Polster von Ihrem Browser angewendet werden und keine Scrollleiste erscheint, sodass die Grafik den gesamten Bildschirm ausfüllen kann. Das ist alles, was wir brauchen, um mit dem Erstellen von 3D-Grafiken zu beginnen.
Teil 1 – Grundlagen der Three.js-Szene
Wenn man mit Three.js und 3D im Allgemeinen arbeitet, gibt es ein paar erforderliche Objekte, die man haben muss. Diese Objekte sind Szene, Kamera und Renderer.
Zuerst sollten Sie eine Szene erstellen. Sie können sich ein Szenenobjekt als Container für jedes andere 3D-Objekt vorstellen, mit dem Sie arbeiten werden. Es repräsentiert die 3D-Welt, die Sie aufbauen werden. Sie können das Szenenobjekt erstellen, indem Sie Folgendes tun:
var scene = new THREE.Scene();
Eine weitere Sache, die man bei der Arbeit mit 3D braucht, ist die Kamera. Stellen Sie sich die Kamera wie die Augen vor, durch die Sie diese 3D-Welt betrachten werden. Bei einer 2D-Visualisierung gibt es normalerweise kein Kamera-Konzept. Was Sie sehen, ist das, was Sie bekommen. Aber in 3D brauchen Sie eine Kamera, um Ihren Blickwinkel zu definieren, da es viele Positionen und Winkel gibt, aus denen Sie eine Szene betrachten könnten. Eine Kamera definiert nicht nur eine Position, sondern auch andere Informationen wie das Sichtfeld oder das Seitenverhältnis.
var camera = new THREE.PerspectiveCamera(
45, // field of view
window.innerWidth / window.innerHeight, // aspect ratio
1, // near clipping plane (beyond which nothing is visible)
1000 // far clipping plane (beyond which nothing is visible)
);
Die Kamera nimmt die Szene zu Anzeigezwecken auf, aber damit wir tatsächlich etwas sehen können, müssen die 3D-Daten in ein 2D-Bild umgewandelt werden. Dieser Prozess wird Rendering genannt und Sie benötigen einen Renderer, um die Szene in Three.js zu rendern. Sie können einen Renderer wie folgt initialisieren:
var renderer = new THREE.WebGLRenderer();
Und dann die Größe des Renderers einstellen. Dies bestimmt die Größe des Ausgabebildes. Sie werden es so einstellen, dass es die Fenstergröße abdeckt.
renderer.setSize(window.innerWidth, window.innerHeight);
Um die Ergebnisse des Renderings anzeigen zu können, müssen Sie die domElement-Eigenschaft des Renderers an Ihren HTML-Inhalt anhängen. Dazu verwenden Sie das leere div-Element mit der ID webgl, das Sie erstellt haben.
document.getElementById('webgl').appendChild(renderer.domElement);
Und nachdem Sie all dies getan haben, können Sie die Render-Methode des Renderers aufrufen, indem Sie die Szene und die Kamera als Argumente übergeben.
renderer.render(
scene,
camera
);
Um die Dinge etwas aufgeräumter zu gestalten, packen Sie alles in eine Funktion namens init und führen Sie diese Funktion aus.
init();
Und jetzt würden Sie nichts sehen... außer einem schwarzen Bildschirm. Keine Sorge, das ist normal. Die Szene funktioniert, aber da Sie keine Objekte in die Szene aufgenommen haben, betrachten Sie im Grunde leeren Raum. Als Nächstes werden wir diese Szene mit 3D-Objekten bevölkern.
Siehe den Pen learning-threejs-01 von Engin Arslan (@enginarslan) auf CodePen.
Objekte zur Szene hinzufügen
Geometrische Objekte in Three.js bestehen aus zwei Teilen. Eine Geometrie, die die Form des Objekts definiert, und ein Material, das die Oberflächenqualität, das Aussehen des Objekts, definiert. Die Kombination dieser beiden Dinge bildet ein Mesh in Three.js, das das 3D-Objekt formt.
Three.js ermöglicht es Ihnen, auf einfache Weise einige einfache Formen wie einen Würfel oder eine Kugel zu erstellen. Sie können eine einfache Kugel erstellen, indem Sie den Radiuswert angeben.
var geo = new THREE.SphereGeometry(1);
Es gibt verschiedene Arten von Materialien, die Sie auf Geometrien anwenden könnten. Materialien bestimmen, wie ein Objekt auf die Szenenbeleuchtung reagiert. Wir können ein Material verwenden, um ein Objekt reflektierend, rau, transparent usw. zu machen. Das Standardmaterial, mit dem Three.js-Objekte erstellt werden, ist das MeshBasicMaterial. MeshBasicMaterial wird von der Szenenbeleuchtung überhaupt nicht beeinflusst. Das bedeutet, dass Ihre Geometrie auch dann sichtbar ist, wenn keine Beleuchtung in der Szene vorhanden ist. Sie können ein Objekt mit einer Farbeigenschaft und einem Hex-Wert an MeshBasicMaterial übergeben, um die gewünschte Farbe für das Objekt festzulegen. Sie werden dieses Material vorerst verwenden, aber es später aktualisieren, damit Ihre Objekte von der Szenenbeleuchtung beeinflusst werden. Derzeit haben Sie keine Beleuchtung in der Szene, daher sollte MeshBasicMaterial eine gute Wahl sein.
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
Sie können Geometrie und Material kombinieren, um ein Mesh zu erstellen, das das 3D-Objekt bildet.
var mesh = new THREE.Mesh(geometry, material);
Erstellen Sie eine Funktion, um diesen Code zur Erstellung einer Kugel zu kapseln. Sie werden in diesem Tutorial nicht mehr als eine Kugel erstellen, aber es ist trotzdem gut, die Dinge ordentlich und sauber zu halten.
function getSphere(radius) {
var geometry = new THREE.SphereGeometry(radius);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var sphere = new THREE.Mesh(geometry, material);
return sphere;
}
var sphere = getSphere(1);
Dann müssen Sie dieses neu erstellte Objekt zur Szene hinzufügen, damit es sichtbar wird.
scene.add(sphere);
Werfen wir noch einmal einen Blick auf die Szene. Sie werden immer noch einen schwarzen Bildschirm sehen.
Siehe den Pen learning-threejs-02 von Engin Arslan (@enginarslan) auf CodePen.
Der Grund, warum Sie derzeit nichts sehen, ist, dass jedes Mal, wenn Sie in Three.js ein Objekt zur Szene hinzufügen, das Objekt in der Mitte der Szene platziert wird, bei den Koordinaten 0, 0, 0 für x, y und z. Das bedeutet einfach, dass Sie derzeit die Kamera und die Kugel an derselben Position haben. Sie sollten die Position eines von beiden ändern, um Dinge sehen zu können.

Lassen Sie uns die Kamera um 20 Einheiten auf der z-Achse verschieben. Dies wird durch Setzen der Eigenschaft position.z der Kamera erreicht. 3D-Objekte haben die Eigenschaften position, rotation und scale, die es Ihnen ermöglichen, sie im 3D-Raum zu transformieren.
camera.position.z = 20;
Sie könnten die Kamera auch auf anderen Achsen bewegen.
camera.position.x = 0;
camera.position.y = 5;
camera.position.z = 20;
Die Kamera ist jetzt höher positioniert, aber die Kugel befindet sich nicht mehr in der Mitte des Bildes. Sie müssen die Kamera darauf ausrichten. Um dies zu tun, können Sie eine Methode namens lookAt auf der Kamera aufrufen. Die Methode lookAt der Kamera bestimmt, auf welchen Punkt die Kamera blickt. Die Punkte im 3D-Raum werden durch Vektoren dargestellt. Sie können also ein neues Vector3-Objekt an diese lookAt-Methode übergeben, um die Kamera auf die Koordinaten 0, 0, 0 blicken zu lassen.
camera.lookAt(new THREE.Vector3(0, 0, 0));
Das Kugellobjekt sieht im Moment nicht sehr glatt aus. Der Grund dafür ist, dass die Funktion SphereGeometry tatsächlich zwei zusätzliche Parameter akzeptiert, die Breiten- und Höhensegmente, die die Auflösung der Oberfläche beeinflussen. Je höher diese Werte sind, desto glatter erscheinen die gekrümmten Oberflächen. Ich setze diesen Wert auf 24 für Breiten- und Höhensegmente.
var geo = new THREE.SphereGeometry(radius, 24, 24);
Siehe den Pen learning-threejs-03 von Engin Arslan (@enginarslan) auf CodePen.
Jetzt erstellen wir eine einfache Ebene-Geometrie, auf der die Kugel sitzen soll. Die Funktion PlaneGeometry benötigt einen width und einen height Parameter. In 3D werden 2D-Objekte standardmäßig nicht von beiden Seiten gerendert, daher müssen Sie dem Material eine side-Eigenschaft übergeben, damit beide Seiten der Ebenen-Geometrie gerendert werden.
function getPlane(w, h) {
var geo = new THREE.PlaneGeometry(w, h);
var material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
side: THREE.DoubleSide,
});
var mesh = new THREE.Mesh(geo, material);
return mesh;
}
Sie können dieses Ebenenobjekt nun ebenfalls zur Szene hinzufügen. Sie werden feststellen, dass die anfängliche Rotation der Ebenen-Geometrie parallel zur y-Achse ist, aber Sie werden sie wahrscheinlich horizontal benötigen, damit sie als Bodenebene fungiert. Es gibt jedoch eine wichtige Sache, die Sie bei Rotationen in Three.js beachten sollten. Sie verwenden Radiant als Einheit, nicht Grad. Eine Drehung von 90 Grad in Radiant entspricht Math.PI/2.
var plane = getPlane(50, 50);
scene.add(plane);
plane.rotation.x = Math.PI/2;
Als Sie das Kugellobjekt erstellten, wurde es mit seinem Mittelpunkt positioniert. Wenn Sie es über die Bodenebene bewegen möchten, können Sie einfach seinen position.y-Wert um den aktuellen Radius erhöhen. Aber das wäre keine programmatische Vorgehensweise. Wenn Sie möchten, dass die Kugel auf der Ebene bleibt, unabhängig von ihrem Radiuswert, sollten Sie den Radiuswert für die Positionierung verwenden.
sphere.position.y = sphere.geometry.parameters.radius;
Siehe den Pen learning-threejs-04 von Engin Arslan (@enginarslan) auf CodePen.
Animationen
Sie sind fast fertig mit dem ersten Teil dieses Tutorials. Aber bevor wir es abschließen, möchte ich veranschaulichen, wie Animationen in Three.js durchgeführt werden. Animationen in Three.js nutzen die requestAnimationFrame-Methode des window-Objekts, die eine gegebene Funktion wiederholt ausführt. Es ist etwas wie eine setInterval-Funktion, aber optimiert für die Browser-Zeichnungsleistung.
Erstellen Sie eine update-Funktion und übergeben Sie den Renderer, die Szene und die Kamera hinein, um die Render-Methode des Renderers innerhalb dieser Funktion auszuführen. Sie werden auch eine requestAnimationFrame-Funktion darin deklarieren und diese update-Funktion rekursiv aus einer Callback-Funktion aufrufen, die an die requestAnimationFrame-Funktion übergeben wird. Es ist besser, dies im Code zu veranschaulichen, als darüber zu schreiben.
function update(renderer, scene, camera) {
renderer.render(scene, camera);
requestAnimationFrame(function() {
update(renderer, scene, camera);
});
}
Alles mag zu diesem Zeitpunkt gleich aussehen, aber der Kernunterschied ist, dass die requestAnimationFrame-Funktion die Szene mit etwa 60 Bildern pro Sekunde rendert, mit einem rekursiven Aufruf der update-Funktion. Das bedeutet, wenn Sie eine Anweisung innerhalb der update-Funktion ausführen, würde diese Anweisung etwa 60 Mal pro Sekunde ausgeführt werden. Fügen wir eine Skalierungsanimation zum Kugellobjekt hinzu. Um das Kugellobjekt aus der update-Funktion auswählen zu können, könnten Sie es als Argument übergeben, aber wir werden eine andere Technik verwenden. Setzen Sie zuerst ein name-Attribut für das Kugellobjekt und geben Sie ihm einen Namen Ihrer Wahl.
sphere.name = 'sphere';
Innerhalb der Update-Funktion können Sie dieses Objekt anhand seines Namens mit der Methode getObjectByName seines Elternobjekts, der Szene, finden.
var sphere = scene.getObjectByName('sphere');
sphere.scale.x += 0.01;
sphere.scale.z += 0.01;
Mit diesem Code skaliert die Kugel nun auf ihren x- und z-Achsen. Unsere Absicht ist jedoch nicht, eine skalierende Kugel zu erstellen. Wir richten die update-Funktion ein, damit Sie sie später für verschiedene Animationen nutzen können. Da Sie nun gesehen haben, wie es funktioniert, können Sie diese Skalierungsanimation entfernen.
Siehe den Pen learning-threejs-05 von Engin Arslan (@enginarslan) auf CodePen.
Teil 2 – Realismus zur Szene hinzufügen
Derzeit verwenden wir MeshBasicMaterial, das die gegebene Farbe auch dann anzeigt, wenn keine Beleuchtung in der Szene vorhanden ist, was zu einem sehr flachen Aussehen führt. Materialien in der realen Welt funktionieren jedoch nicht so. Die Sichtbarkeit der Oberfläche in der realen Welt hängt davon ab, wie viel Licht von der Oberfläche zu unseren Augen zurückreflektiert wird. Three.js bietet eine Reihe von verschiedenen Materialien, die eine bessere Annäherung daran bieten, wie sich Oberflächen in der realen Welt verhalten, und eines davon ist MeshStandardMaterial. MeshStandardMaterial ist ein physikalisch basiertes Rendering-Material, das Ihnen helfen kann, fotorealistische Ergebnisse zu erzielen. Dies ist die Art von Material, die moderne Spiel-Engines wie Unreal oder Unity verwenden und ein Industriestandard in Gaming und visuellen Effekten ist.
Beginnen wir mit der Verwendung von MeshStandardMaterial für unsere Objekte und ändern die Farbe der Materialien auf Weiß.
var material = new THREE.MeshStandardMaterial({
color: 0xffffff,
});
Sie erhalten an diesem Punkt erneut ein schwarzes Rendering. Das ist normal. Damit Objekte sichtbar sind, benötigen wir Lichter in der Szene. Dies war keine Voraussetzung für MeshBasicMaterial, da es ein einfaches Material ist, das unter allen Bedingungen die gegebene Farbe anzeigt, aber andere Materialien erfordern eine Interaktion mit Licht, um sichtbar zu sein. Erstellen wir eine Funktion zum Erstellen von SpotLight. Wir werden zwei Scheinwerfer mit dieser Funktion erstellen.
function getSpotLight(color, intensity) {
var light = new THREE.SpotLight(color, intensity);
return light;
}
var spotLight_01 = getSpotlight(0xffffff, 1);
scene.add(spotLight_01);
Sie könnten zu diesem Zeitpunkt bereits etwas sehen. Positionieren Sie das Licht und die Kamera etwas anders für eine bessere Rahmung und Schattierung. Erstellen Sie auch ein zweites Licht.
var spotLight_02 = getSpotlight(0xffffff, 1);
scene.add(spotLight_02);
camera.position.x = 0;
camera.position.y = 6;
camera.position.z = 6;
spotLight_01.position.x = 6;
spotLight_01.position.y = 8;
spotLight_01.position.z = -20;
spotLight_02.position.x = -12;
spotLight_02.position.y = 6;
spotLight_02.position.z = -10;
Damit haben Sie zwei Lichtquellen in der Szene, die die Kugel von zwei verschiedenen Positionen aus beleuchten. Die Beleuchtung hilft ein wenig beim Verständnis der Dimensionalität der Szene, aber die Dinge sehen immer noch extrem unecht aus, da der Beleuchtung eine entscheidende Komponente fehlt: die Schatten!
Das Rendern eines Schattens in Three.js ist leider nicht ganz einfach. Das liegt daran, dass Schatten rechenintensiv sind und wir die Schattenwiedergabe an mehreren Stellen aktivieren müssen. Zuerst müssen Sie dem Renderer mitteilen, dass er mit dem Rendern von Schatten beginnen soll.
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
Dann müssen Sie dem Licht mitteilen, dass es Schatten wirft. Tun Sie dies in der Funktion getSpotLight.
light.castShadow = true;
Sie sollten den Objekten auch mitteilen, dass sie Schatten werfen und/oder empfangen sollen. In diesem Fall lassen wir die Kugel Schatten werfen und die Ebene Schatten empfangen.
mesh.castShadow = true;
mesh.receiveShadow = true;
Nach all diesen Einstellungen sollten wir Schatten in der Szene sehen. Anfangs könnten sie von etwas geringerer Qualität sein. Sie können die Auflösung der Schatten erhöhen, indem Sie die Schattenkarten-Größe des Lichts einstellen.
light.shadow.mapSize.x = 4096;
light.shadow.mapSize.y = 4096;
MeshStandardMaterial hat einige Eigenschaften wie roughness und metalness, die die Interaktion der Oberfläche mit dem Licht steuern. Die Eigenschaften nehmen Werte zwischen 0 und 1 an und steuern das entsprechende Verhalten der Oberfläche. Erhöhen Sie den Rauheitswert des Ebenenmaterials auf 1, um zu sehen, wie die Oberfläche mehr wie Gummi aussieht, da die Reflexionen verschwommener werden.
// material adjustments
var planeMaterial = plane.material;
planeMaterial.roughness = 1;
Wir werden hierfür jedoch keinen Wert von 1 verwenden. Sie können gerne mit Werten experimentieren, aber setzen Sie ihn für die Rauheit auf 0.65 und für die Metalligkeit auf 0.75 zurück.
planeMaterial.roughness = 0.65;
planeMaterial.metalness = 0.75;
Obwohl die Szene jetzt vielversprechender aussehen sollte, ist es immer noch schwer, sie als realistisch zu bezeichnen. Die Wahrheit ist, dass es ohne Textur-Maps sehr schwierig ist, Fotorealismus in 3D zu erzielen.
Siehe den Pen learning-threejs-06 von Engin Arslan (@enginarslan) auf CodePen.
Textur-Maps
Textur-Maps sind 2D-Bilder, die auf ein Material gemappt werden können, um Oberflächendetails zu liefern. Bisher erhielten Sie nur solide Farben auf den Oberflächen, aber mit einer Textur-Map können Sie jedes beliebige Bild auf eine Oberfläche abbilden. Textur-Maps werden nicht nur zur Manipulation von Farbinformationen von Oberflächen verwendet, sondern auch zur Manipulation anderer Oberflächeneigenschaften wie Reflexivität, Glanz, Rauheit usw.
Texturen können aus fotografischen Quellen stammen oder auch von Grund auf neu gemalt werden. Damit eine Textur in einem 3D-Kontext nützlich ist, sollte sie auf eine bestimmte Weise erfasst werden. Bilder, die Reflexionen oder Schatten enthalten, oder Bilder, bei denen die Perspektive zu stark verzerrt ist, eignen sich nicht gut als Textur-Maps. Es gibt mehrere spezielle Websites zum Finden von Texturen online. Eine davon ist textures.com, die ein ziemlich gutes Archiv hat. Sie bieten einige kostenlose Download-Optionen, erfordern aber eine Registrierung. Eine weitere Website für 3D-Texturen ist Megascans, die hochauflösende, qualitativ hochwertige Umgebungs-Scans mit hoher Produktionsqualität liefert.
Ich habe für dieses Beispiel eine Website namens mb3d.co.uk verwendet. Diese Seite bietet nahtlose, frei nutzbare Texturen. Eine nahtlose Textur bedeutet eine Textur, die mehrmals auf der Oberfläche wiederholt werden kann, ohne Unterbrechungen an den Rändern. Dies ist der Link zur Texturdatei, die ich verwendet habe. Ich habe die Größe auf 512 Pixel Breite und Höhe reduziert und die Bilddatei mit einem Online-Dienst namens ezgif in ein Data-URI konvertiert, um sie als Teil des JavaScript-Codes einzubinden, anstatt sie als separaten Asset zu laden. (Hinweis: Schließen Sie keine tags ein, wenn Sie die Daten ausgeben, wenn Sie diesen Dienst verwenden)
Erstellen Sie eine Funktion, die das von uns generierte Data-URI zurückgibt, damit wir diesen riesigen String nicht mitten im Code haben.
function getTexture() {
var data = 'data:image/jpeg;base64,/...'; // paste your data URI inside the quotation marks.
return data
}
Als Nächstes müssen Sie die Textur laden und auf die Ebenenoberfläche anwenden. Dazu verwenden Sie den TextureLoader von Three.js. Nach dem Laden der Textur laden Sie die Textur in die map-Eigenschaft des gewünschten Materials, um sie als Farb-Map auf der Oberfläche zu haben.
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load(getTexture());
planeMaterial.map = texture;
Die Dinge sehen im Moment ziemlich hässlich aus, da die Textur auf der Oberfläche pixelig ist. Das Bild wird zu stark gestreckt, um die gesamte Oberfläche zu bedecken. Sie können stattdessen das Bild wiederholen lassen, anstatt es zu skalieren, damit es nicht so pixelig wird. Dazu müssen Sie die Eigenschaften wrapS und wrapT auf der gewünschten Map auf THREE.RepeatWrapping setzen und einen Wiederholungswert angeben. Da Sie dies auch für andere Arten von Maps (wie bump oder roughness Map) tun werden, ist es besser, eine Schleife dafür zu erstellen.
var repetition = 6;
var textures = ['map']// we will add 'bumpMap' and 'roughnessMap'
textures.forEach((mapName) => {
planeMaterial[mapName].wrapS = THREE.RepeatWrapping;
planeMaterial[mapName].wrapT = THREE.RepeatWrapping;
planeMaterial[mapName].repeat.set(repetition, repetition);
});
Das sollte viel besser aussehen. Da die von Ihnen verwendete Textur nahtlos ist, werden Sie keine Unterbrechungen an den Rändern bemerken, wo die Wiederholung stattfindet.
Das Laden einer Textur ist tatsächlich ein asynchroner Vorgang. Das bedeutet, dass Ihre 3D-Szene generiert wird, bevor die Bilddatei geladen ist. Da Sie die Szene jedoch kontinuierlich mit requestAnimationFrame rendern, verursacht dies in diesem Beispiel keine Probleme. Wenn Sie dies nicht tun würden, müssten Sie Callbacks oder andere asynchrone Methoden verwenden, um die Lade reihenfolge zu verwalten.
Siehe den Pen learning-threejs-07 von Engin Arslan (@enginarslan) auf CodePen.
Andere Textur-Maps
Wie im vorherigen Kapitel erwähnt, werden Texturen nicht nur zur Definition der Farbe von Oberflächen verwendet, sondern auch zur Definition anderer Eigenschaften. Eine weitere Möglichkeit, wie Texturen verwendet werden können, sind Bump-Maps. Wenn sie als Bump-Map verwendet werden, simulieren die Helligkeitswerte der Textur einen Höheneffekt.
planeMaterial.bumpMap = texture;
Die Bump-Map sollte auch die gleiche Wiederholungskonfiguration wie die Farb-Map verwenden, also nehmen Sie sie in das textures-Array auf.
var textures = ['map', 'bumpMap'];
Bei einer Bump-Map ist der Wert eines Pixels heller, desto höher erscheint die entsprechende Oberfläche. Aber eine Bump-Map verändert die Oberfläche nicht tatsächlich, sie manipuliert nur, wie das Licht mit der Oberfläche interagiert, um die Illusion einer unebenen Topologie zu erzeugen. Die Bump-Stärke wirkt im Moment etwas zu stark. Bump-Maps funktionieren am besten, wenn sie in subtilen Mengen verwendet werden. Ändern wir also den Parameter bumpScale auf etwas Niedrigeres für einen subtileren Effekt.
planeMaterial.bumpScale = 0.01;
Beachten Sie, wie diese Textur einen großen Unterschied im Aussehen gemacht hat. Die Reflexionen sind nicht mehr perfekt, sondern schön gebrochen, wie sie im wirklichen Leben wären. Ein weiterer Karten-Slot, der für StandardMaterial verfügbar ist, ist die roughness map. Eine Textur-Map, die als roughness map verwendet wird, ermöglicht es Ihnen, die Schärfe von Reflexionen anhand der Helligkeitswerte eines gegebenen Bildes zu steuern.
planeMaterial.roughnessMap = texture;
var textures = ['map', 'bumpMap', 'roughnessMap'];
Laut der Three.js-Dokumentation funktioniert StandardMaterial am besten in Verbindung mit einer environment map. Eine Umgebungskarte simuliert eine ferne Umgebung, die sich auf den reflektierenden Oberflächen in der Szene spiegelt. Sie hilft wirklich, wenn Sie versuchen, Reflexivität auf Objekten zu simulieren. Umgebungskarten in Three.js liegen in Form von Cube Maps vor. Eine Cube Map ist eine Panoramansicht einer Szene, die in einen Würfel abgebildet wird. Eine Cube Map besteht aus 6 separaten Bildern, die jeder Seite eines Würfels entsprechen. Da das Laden von 6 zusätzlichen Bildern in einem Online-Editor etwas zu viel Arbeit wäre, werden wir in diesem Beispiel keine Umgebungskarte verwenden. Aber um dieses Kugellobjekt etwas interessanter zu gestalten, fügen wir ihm auch eine roughness map hinzu. Sie werden diese Textur verwenden, aber mit 320x320 Pixel Größe und als Data-URI.
Erstellen Sie eine neue Funktion namens getMetalTexture.
function getMetalTexture() {
var data = 'data:image/jpeg;base64,/...'; // paste your data URI inside the quotation marks.
return data
}
Und wenden Sie sie auf das Kugel-Material als bumpMap und roughnessMap an.
var sphereMaterial = sphere.material;
var metalTexture = textureLoader.load(getMetalTexture());
sphereMaterial.bumpMap = metalTexture;
sphereMaterial.roughnessMap = metalTexture;
sphereMaterial.bumpScale = 0.01;
sphereMaterial.roughness = 0.75;
sphereMaterial.metalness = 0.25;
Siehe den Pen learning-threejs-08 von Engin Arslan (@enginarslan) auf CodePen.
Abschluss!
Sie sind fast fertig! Hier nehmen Sie nur noch ein paar kleine Anpassungen vor. Die endgültige Version dieser Szenen-Datei finden Sie in diesem Pen.
Geben Sie den Lichtern eine Farbe, die nicht weiß ist. Beachten Sie, wie Sie tatsächlich CSS-Farbwerte als Zeichenketten verwenden können, um Farben anzugeben.
var spotLight_01 = getSpotlight('rgb(145, 200, 255)', 1);
var spotLight_02 = getSpotlight('rgb(255, 220, 180)', 1);
Und fügen Sie den Lichtern eine subtile zufällige Flackeranimation hinzu, um der Szene etwas Leben einzuhauchen. Weisen Sie zuerst den Lichtern eine name-Eigenschaft zu, damit Sie sie innerhalb der update-Funktion mit der Methode getObjectByName finden können.
spotLight_01.name = 'spotLight_01';
spotLight_02.name = 'spotLight_02';
Und dann erstellen Sie die Animation innerhalb der update-Funktion mithilfe der Funktion Math.random().
var spotLight_01 = scene.getObjectByName('spotLight_01');
spotLight_01.intensity += (Math.random() - 0.5) * 0.15;
spotLight_01.intensity = Math.abs(spotLight_01.intensity);
var spotLight_02 = scene.getObjectByName('spotLight_02');
spotLight_02.intensity += (Math.random() - 0.5) * 0.05;
spotLight_02.intensity = Math.abs(spotLight_02.intensity);
Und als Bonus habe ich in der Szenen-Datei das OrbitControls-Skript für die Three.js-Kamera enthalten, was bedeutet, dass Sie tatsächlich mit der Maus auf der Szene ziehen können, um mit der Kamera zu interagieren! Ich habe auch dafür gesorgt, dass die Szene mit der sich ändernden Fenstergröße skaliert. Dies habe ich aus Bequemlichkeitsgründen mit einem externen Skript erreicht.
Siehe den Pen learning-threejs-final von Engin Arslan (@enginarslan) auf CodePen.
Nun ist diese Szene einer fotorealistischen Darstellung schon ziemlich nahe gekommen. Es fehlen jedoch noch viele Teile. Die Kugelkugel ist aufgrund mangelnder Reflexionen und Umgebungsbeleuchtung zu dunkel. Die Bodenebene wirkt in flachen Winkeln zu flach. Das Profil der Kugel ist zu perfekt – es ist CG-perfekt (Computergrafik). Die Beleuchtung ist nicht so realistisch, wie sie sein könnte; sie verliert (verliert Intensität) mit der Entfernung von der Quelle. Sie sollten wahrscheinlich auch Partikeleffekte, Kameraanimationen und Post-Processing-Filter hinzufügen, wenn Sie damit ganz durchstarten wollen. Aber dies sollte immer noch ein gutes Beispiel sein, um die Leistungsfähigkeit von Three.js und die Qualität der Grafiken zu veranschaulichen, die Sie im Browser erstellen können. Für weitere Informationen darüber, was Sie mit dieser erstaunlichen Bibliothek erreichen können, sollten Sie unbedingt meinen neuen Kurs bei Lynda.com zu diesem Thema ansehen!
Danke, dass Sie bis hierher gekommen sind! Ich hoffe, Ihnen hat dieser Beitrag gefallen, und Sie können sich gerne mit Fragen an mich wenden, entweder @inspiratory auf Twitter oder auf meiner Website!
Tolles Tutorial, Prost.
Vielen Dank für das tolle Tutorial!