Hallo habr Ich präsentiere Ihnen die Übersetzung des Artikels "JavaScript in 3D: eine Einführung in Three.js" von Bret Cameron.Einleitung
Three.js ist ein mächtiges Werkzeug. Es ist hilfreich, 3D-Design in einem Browser mit akzeptabler Leistung zu verwenden. Erste Schritte Three.js kann schwierig sein, insbesondere wenn Sie noch nie zuvor in die 3D-Programmierwelt eingetaucht sind.
Ich habe einige grundlegende Erfahrungen mit der Unity- und C # -Spiel-Engine, aber dennoch sind viele der Konzepte für mich neu. Ich bin zu dem Schluss gekommen, dass es für Anfängerentwickler nur sehr wenige Ressourcen gibt, und habe mich daher entschlossen, diesen Artikel zu schreiben. Darin werden die Grundelemente von Three.js Szenen von Polygonnetzen und Materialien über Geometrie bis hin zu Ladern und vielem mehr betrachtet.
Am Ende dieses Artikels erhalten Sie ein solides Verständnis der grundlegenden Aspekte, die erforderlich sind, um Ihrem zukünftigen Webprojekt eine zusätzliche Dimension hinzuzufügen.
Drei Beispiele von
Ben Houston ,
Thomas Diewald und
StrykerDoesAnimation .
Vektoren und Container - Grundbausteine
Oft gibt es zwei Hauptklassen in Three.js -
Vector3 und
Box3 . Wenn Sie 3D noch nicht kennen, klingt dies vielleicht ein bisschen abstrakt, aber Sie werden sie öfter treffen.
Vector3
Die grundlegendste 3D-Klasse mit drei Zahlen:
x, y und z . Zahlen sind die Koordinaten eines Punktes im 3D-Raum oder die Richtung und Länge. Zum Beispiel:
const vect = new THREE.Vector3(1, 1, 1);
Die meisten Konstruktoren in Three.js akzeptieren Objekte vom Typ
Vector3 als Eingabeargumente, z. B.
Box3Box3
Diese Klasse repräsentiert Quader (3D-Container). Seine Hauptaufgabe besteht darin, einen Container um andere Objekte zu erstellen - und das ist alles, der kleinste Quader, in den ein 3D-Objekt passt. Jede
Box3 ist um die
x-, y- und z- Achse ausgerichtet
. Ein Beispiel zum Erstellen eines Containers mit
Vector3 :
const vect = new THREE.Vector3(1, 1, 1); const box = new THREE.Box3(vect);
Ein Beispiel zum Erstellen eines Containers um ein vorhandenes 3D-Objekt:
const box = new THREE.Box3(); box.setFromObject(object);
Sie können Grids ohne dieses fundierte Wissen erstellen. Sobald Sie jedoch mit der Entwicklung oder Änderung Ihrer Modelle beginnen, sind diese Klassen auf jeden Fall hilfreich. Jetzt werden wir uns von Abstraktionen zu sichtbareren Dingen entfernen.
Polygonnetz
In Three.js ist
Mesh das wichtigste visuelle Element auf der Bühne. Dies ist ein 3D-Objekt aus dreieckigen Rechtecken (Polygonnetz). Es besteht aus zwei Objekten:
Geometrie - bestimmt die Form,
Material - bestimmt das Aussehen.
Ihre Definitionen wirken möglicherweise etwas verwirrend (z. B. enthält die
Geometrieklasse möglicherweise Informationen zu Farben), aber der Hauptunterschied besteht genau darin.
Geometrie
Abhängig von der gewünschten Aufgabe können Sie die Geometrie in Three.js definieren oder eine andere aus einer Datei importieren.
Mit Funktionen wie
THREE.TorusKnotGeometry können wir komplexe Objekte mit einer einzigen Codezeile erstellen. Wir werden bald darauf eingehen, aber zunächst über einfachere Formen nachdenken.
Die einfachste 3D-Figur, Quader oder Container, kann durch die Parameter
Breite ,
Höhe und
Tiefe angegeben werden.
const geometry = new THREE.BoxGeometry( 20, 20, 20 );
Für eine Kugel ist der Wert der Parameter
radius ,
widthSegments und
heightSegments minimal . Die letzten beiden Variablen geben an, mit wie vielen Dreiecken das Modell die Kugel darstellen soll: Je größer die Zahl, desto glatter wird sie.
const geometry = new THREE.SphereGeometry( 20, 64, 64 );
Wenn wir scharfe oder dreieckige Formen herstellen möchten, können wir einen Kegel verwenden. Seine Argumente sind eine Kombination der Argumente der beiden vorhergehenden Figuren. Nachfolgend geben wir
Radius ,
WidthSegments und
RadialSegments vor .
const geometry = new THREE.ConeBufferGeometry( 5, 20, 32 );
Dies ist nur ein Teil der häufigsten Zahlen. Three.js enthält viele Formen, die in der Dokumentation zu finden sind. In diesem Artikel werden weitere interessante Formulare vorgestellt, die auf der
TorusKnotGeometry- Methode
basieren .
Warum sehen diese Formen genau so aus, wie sie aussehen? Diese Frage würde den Rahmen dieses Artikels sprengen, aber ich rate Ihnen dringend, mit Parameterwerten zu experimentieren, da Sie mit einer Codezeile sehr interessante Formen erhalten können!
const geometry = new THREE.TorusKnotGeometry(10, 1.3, 500, 6, 6, 20);
https://codepen.io/BretCameron/pen/gOYqORgMaterial
Geometrie definiert die Form unserer 3D-Objekte, nicht jedoch deren Erscheinungsbild. Um dies zu beheben, benötigen wir Materialien.
Three.js bietet 10 Materialien an, von denen jedes seine eigenen Vorteile und anpassbaren Parameter hat. Wir werden nur einen Teil der nützlichsten betrachten.

MeshNormalMaterial
Nützlich für den schnellen Start und Start.Wir beginnen mit
MeshNormalMaterial , dem mehrfarbigen Material, das wir in den obigen Beispielen verwendet haben. Sie entspricht den normalen Vektoren im RGB-Bedienfeld, dh, die Position des Vektors im 3D-Raum wird anhand von Farben bestimmt.
const material = new THREE.MeshNormalMaterial();
Beachten Sie, dass Sie den CSS-Filter verwenden und die Sättigung ändern können, wenn Sie die Farbe des Materials ändern möchten:
filter: hue-rotate(90deg) .
Meiner Erfahrung nach ist dieses Material für eine schnelle Schicht und den Start nützlicher. Für eine bessere Kontrolle Ihrer Objekte ist es besser, etwas anderes zu verwenden.
Meshbasismaterial
Nützlich, wenn nur das Skelett angezeigt wird.Wenn Sie der Figur eine einzelne Farbe geben möchten, können Sie
MeshBasicMaterial nur verwenden, wenn keine Beleuchtung angewendet wird. Ich fand es nützlich, dieses Material beim Rendern des Modellskeletts zu verwenden. Um nur das Skelett zu zeichnen, müssen Sie
{wireframe: true} als Parameter übergeben.
const material = new THREE.MeshBasicMaterial({ wireframe: true, color: 0xdaa520 });
Der Hauptnachteil dieses Materials ist, dass Informationen über die Tiefe des Materials vollständig verloren gehen. Jedes Material hat die Option, nur das Skelett anzuzeigen, aber nur ein Material löst das Problem der fehlenden Tiefe -
MeshDepthMaterialMeshhambertmaterial
Nützlich für hohe Leistung bei geringer Genauigkeit.Dies ist das erste Material, das Licht berücksichtigt, daher müssen Sie unserer Szene etwas Licht hinzufügen. Im folgenden Code fügen wir Scheinwerfer mit einem gelben Farbton hinzu, um einen wärmeren Effekt zu erzielen.
const scene = new THREE.Scene(); const frontSpot = new THREE.SpotLight(0xeeeece); frontSpot.position.set(1000, 1000, 1000); scene.add(frontSpot); const frontSpot2 = new THREE.SpotLight(0xddddce); frontSpot2.position.set(-500, -500, -500); scene.add(frontSpot2);
Fügen Sie nun Material für unsere Figur hinzu. Da unsere Figur wie eine Dekoration ist, schlage ich vor, eine goldenere Farbe hinzuzufügen. Ein weiterer
emittierender Parameter ist die Farbe des Objekts, das vom Objekt selbst stammt (ohne Lichtquelle). Oft funktioniert dies besser als dunkle Farbe - zum Beispiel als dunkle Graustufen, wie im folgenden Beispiel
const material = new THREE.MeshLambertMaterial({ color: 0xdaa520, emissive: 0x111111, });
Wie Sie im folgenden Beispiel sehen können, ist die Farbe mehr oder weniger korrekt, aber die Art und Weise, wie sie mit dem Licht interagiert, trägt nicht zum Realismus bei. Um dies zu beheben, müssen Sie
MeshPhongMaterial oder
MeshStandardMaterial verwenden.MeshPhongMaterial
Nützlich für mittlere Leistung und mittlere Genauigkeit.Dieses Material bietet einen Kompromiss zwischen Leistung und Rendering-Genauigkeit. Daher ist dieses Material eine gute Option für eine Anwendung, die produktiv sein muss und ein genaueres Rendering als
MeshLambertMaterial bietet.Jetzt können wir die
Spiegeleigenschaft ändern, die die Helligkeit und Farbe der Oberflächenreflexion beeinflusst. Wenn die Emissionseigenschaft normalerweise dunkel ist, eignet sich
Specular am besten für helle Farben. Unten verwenden wir hellgrau.
const material = new THREE.MeshPhongMaterial({ color: 0xdaa520, emissive: 0x000000, specular: 0xbcbcbc, });
Optisch reflektiert das Bild von oben das Licht überzeugender, aber immer noch nicht perfekt. Weißes Licht ist zu hell und das Material sieht eher gerippt als metallisch aus (und wir bemühen uns darum). Mit
MeshStandardMaterial können wir ein besseres Ergebnis
erzielen.MeshStandartMaterial
Nützlich für hohe Genauigkeit bei geringer Produktivität.Dies ist das genaueste Material von allen, obwohl seine Verwendung die Kosten eines höheren Stromverbrauchs mit sich bringt.
MeshStandartMaterial wird mit zusätzlichen
Metall- und
Rauheitsparametern verwendet , die jeweils einen Wert zwischen 0 und 1
annehmen .
Der
Metalness- Parameter beeinflusst, wie das Objekt reflektiert und nähert sich der Natur des Metalls an. Dies liegt daran, dass leitende Materialien wie Metalle im Gegensatz zu Dielektrika wie Keramik unterschiedliche Reflexionseigenschaften aufweisen.
Rauheit fügt eine zusätzliche Ebene für die Anpassung hinzu. Sie können sich das Gegenteil von Glanz vorstellen: 0 - sehr glänzend, 1 - sehr matt.
const material = new THREE.MeshStandardMaterial({ color: 0xfcc742, emissive: 0x111111, specular: 0xffffff, metalness: 1, roughness: 0.55, });
Dies ist das realistischste Material von allen in Three.js vorgestellten, aber auch das ressourcenintensivste
Die Materialien, die wir unten besprochen haben, sind die, die ich am häufigsten getroffen habe, und Sie können alle Optionen im Dock sehen.
Lader
Wie oben erläutert, können Sie Geometrie- und Polygonnetze manuell definieren. In der Praxis laden Benutzer ihre Geometrien häufig aus Dateien. Glücklicherweise hat Three.js nur wenige unterstützte Downloader, die viele 3D-Formate unterstützen.
Der Haupt-
ObjectLoader lädt die JSON-Datei im
JSON-Objekt- / Szenenformat . Die meisten Bootloader müssen manuell importiert werden. Hier finden Sie eine vollständige Liste der unterstützten Bootloader, die Sie importieren können. Nachstehend finden Sie eine kleine Liste der importierbaren Elemente.
Das empfohlene Format für die Online-Anzeige ist GLTF, da das Format darauf abzielt, "Assets zur Laufzeit bereitzustellen, kompakt zu übertragen und schnell herunterzuladen".
Natürlich kann es viele Gründe geben, einen bestimmten Dateityp zu bevorzugen (z. B. wenn Qualität Priorität hat oder Genauigkeit für den 3D-Druck erforderlich ist). Die beste Online-Leistung wird beim Importieren von GLTF erzielt.
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import model from '../models/sample.gltf'; let loader = new GLTFLoader(); loader.load(model, function (geometry) {
Alles zusammen
Einer der Gründe, warum Three.js einschüchternd wirkt, ist, dass Sie mit nur wenigen Codezeilen etwas von Grund auf neu erstellen können. In jedem obigen Beispiel mussten wir eine Szene und eine Kamera erstellen. Der Einfachheit halber habe ich diesen Code außerhalb des Bereichs der Überprüfung belassen, aber im Moment werden wir sehen, wie er zusammen aussehen wird.
Die Art und Weise, wie Sie Ihren Code organisieren, liegt bei Ihnen. In einfacheren Beispielen, wie in diesem Artikel, ist es sinnvoll, den gesamten Code an einer Stelle zu schreiben. In der Praxis ist es jedoch sinnvoll, die einzelnen Elemente zu trennen, um die Codebasis und deren Verwaltung zu erweitern.
Der Einfachheit halber betrachten wir Elemente, die als ein einzelnes Objekt gezeichnet werden, sodass wir den gesamten Code in einer Datei speichern.
Muss ich ein Framework verwenden?
Schließlich ist es Zeit zu diskutieren, ob Three.js mit Ihrem bevorzugten Framework verwendet werden soll. Im Moment gibt es ein gutes React
-Three-Fibre- Paket für React. Für React-Benutzer bietet die Verwendung eines solchen Pakets offensichtliche Vorteile: Sie pflegen eine Struktur für die Arbeit mit Komponenten, mit der Sie Code wiederverwenden können.
Anfängern
rate ich, mit dem üblichen
Vanila JS zu beginnen , da die meisten Online-Materialien, die über Three.js geschrieben wurden, sich auf Three.js auf Vanila JS beziehen. Aufgrund meiner Lernerfahrung kann es verwirrend und schwierig sein, dies durch ein Paket zu lernen. Beispielsweise müssen Sie Three.js-Objekte und -Methoden in Komponenten und Requisiten übersetzen. (Sobald Sie Three.js lernen, können Sie jedes Paket verwenden).
Hinzufügen von Three.js zum Framework
Three.js bietet ein HTML-Objekt (am häufigsten als
renderer.domElement bezeichnet ), das zu jedem HTML-Objekt in Ihrer Anwendung hinzugefügt werden kann. Wenn Sie zum Beispiel ein
div mit
id = ”threejs” haben , können Sie einfach den folgenden Code in Ihren Three.js-Code einfügen:
document.getElementById('threejs').appendChild(renderer.domElement);
Einige Frameworks haben bevorzugte Pfade, um auf die DOM-Knoten des Baums zuzugreifen. Zum Beispiel
ref in React,
$ ref in Vue oder
ngRef in Angular und es sieht aus wie ein gewaltiges Plus vor dem Hintergrund des direkten Zugriffs auf DOM-Elemente. Schauen wir uns als Beispiel eine schnelle Implementierung für React an.
Strategie für die Reaktion
Wenn Sie Reagieren verwenden, gibt es eine Möglichkeit, Three.js-Dateien in eine Ihrer Komponenten einzubetten. In die Datei
ThreeEntryPoint.js schreiben wir den folgenden Code:
export default function ThreeEntryPoint(sceneRef) { let renderer = new THREE.WebGLRenderer();
Wir exportieren dies als eine Funktion, die ein Argument akzeptiert: einen Verweis auf ein Element in unserer Komponente. Jetzt können wir unsere Komponente erstellen
import React, { Component } from 'react'; import ThreeEntryPoint from './threejs/ThreeEntryPoint'; export default class ThreeContainer extends Component { componentDidMount() { ThreeEntryPoint(this.scene); } render() { return ( <> <div ref={element => this.scene = element} /> </> ); } }
Die importierte
ThreeEntryPoint- Funktion
muss in der
componentDidMount- Methode aufgerufen und das neue
div unter Verwendung von Referenzen als Argument übergeben werden
Als Beispiel für diesen Ansatz können Sie das Repository klonen und selbst ausprobieren:
https://github.com/BretCameron/three-js-sample .
Fazit
Ich kann noch viel über Three.js sagen, aber ich hoffe, dieser Artikel hat Ihnen genügend Informationen geliefert, um mit der Verwendung dieser leistungsstarken Technologie zu beginnen. Als ich anfing, Three.js zu lernen, konnte ich keine einzige Ressource wie diesen Artikel finden. Ich hoffe, ich habe dazu beigetragen, diese Technologie für Anfänger zugänglicher zu machen.