Willkommen zu unserem 3 Teil unserer Serie zu den WebGL Grundlagen. Diesmal werden wir einige echte 3D Objekte in Motion sehen.

Sobald Sie diesen Teil durchgearbeitet haben und die WebGL-Datei im Browser abspielen, sehen Sie das folgende Ergebnis:

For privacy reasons YouTube needs your permission to be loaded. For more details, please see our Datenschutzerklärung.

Ein wichtiger Hinweis: Dieser Teil richtet sich an Personen mit fortgeschrittenen Programmierkenntnissen, aber ohne wirkliche Erfahrung mit 3D-Grafiken. Sie werden ein gutes Verständnis für den Code mitbringen und es zum Laufen bringen, so dass Sie so schnell wie möglich mit der Erstellung einer eigenen Website in 3D beginnen können.

Es existieren zwei verschiedene Möglichkeiten, den Code für dieses Beispiel zu erhalten. In den Browsereinstellungen mit „View Source“, während Sie sich die Live-Version ansehen oder wenn Sie GitHub verwenden, können Sie es aus dem Repository kopieren. Unabhängig davon für welchen Weg Sie sich entscheiden, sollten Sie ihren bevorzugten Texteditor herunterladen und Sie den Code genau ansehen.

Die Unterschiede zwischen dem Code für diesen Teil und dem vorherigen konzentrieren sich vollständig auf die Funktionen animate, initBuffers und drawScene. Wenn Sie nun nach unten scrollen, um zu animieren sehen Sie eine erste kleine Änderung. Die Variablen, die sich an den aktuellen Rotationszustand der beiden Objekte in der Szene erinnern wurden umbenannt. Davor wurden Sie als rTri und rSquare bezeichnet. Wir haben auch die Drehrichtung des Würfels umgekehrt:

Copy to Clipboard

Gehen wir nun nach oben zu drawScene. Direkt über der Funktionsdeklaration haben wir Definitionen für die neuen Variablen.

Copy to Clipboard

Als nächstes kommt der function header, gefolgt von unserem SetUp-Code und dem Code, um die Pyramide zu zeichnen. Wenn das alles erledigt ist, drehen wir es um die Y-Achse, so wie wir es im vorherigen Teil für das Dreieck bereits getan haben:

Copy to Clipboard

…und dann zeichnen wir es. Der einzige Unterschied zwischen dem Code im letzten Teil, welcher das bunte Dreieck gezeichnet hat und dem neuen Code zum Zeichnen der Pyramide besteht darin, dass es mehr Scheitelpunkte und ebenso mehr Farben gibt, dass alle in initBuffers behandelt werden. Das bedeutet, dass der Code bis auf eine Namensänderung der von uns verwendeten Puffer identisch ist:

Copy to Clipboard

Das war recht einfach. Schauen wir uns nun den Code für den Würfel an. Der erste Schritt besteht darin, es zu drehen. Dieses Mal drehen wir uns nicht nur um die X-Achse, sondern um eine Achse, die nach oben, nach unten und zum Nutzer gerichtet ist:

Copy to Clipboard

Als nächstes zeichnen wir den Würfel. Das wird ein wenig komplizierter, Es existieren drei Möglichkeiten, wie wir einen Würfel zeichnen können:

1. Verwenden Sie einen einzelnen Dreiecksstreifen. Wenn der ganze Würfel eine Farbe hätte, wäre dies ziemlich einfach – wir könnten die Vertex-Positionen, die wir bis jetzt genutzt haben verwenden, um eine Vorderseite zu zeichnen. Anschließend fügen wir zwei weitere Punkte hinzu, um eine weitere Fläche hinzu und zwei weitere für eine andere und so weiter. Das ist ein effizienter Weg. Allerdings soll jedes Gesicht eine andere Farbe haben. Da jeder Scheitelpunkt eine Ecke des Würfels angibt und jede Ecke zwischen drei Flächen geteilt wird, müssten wir jeden Scheitelpunkt dreimal angeben und das wäre so knifflig, dass wir in einem so frühen Lernstadium auf weitere Erläuterungen verzichten werden.

2. Wir könnten manipulieren und unseren Würfel zeichnen, indem wir sechs verschiedene Quadrate zeichnen. Für jedes Gesicht eines mit getrennten Sätzen von Scheitelpositionen und Farben für jedes einzelne. Das ist jedoch keine gute Lösung. Jedes Mal, wenn WebGL aufgefordert wird ein anderes Objekt in einer Szene zu zeichnen, dies einen gewissen Zeitaufwand kostet. Da ist es viel besser eine minimale Anzahl von drawArrays zu haben.

3. Die letzte Option besteht darin, den Würfel als sechs Quadrate zu spezifizieren, die jeweils aus zwei Dreiecken bestehen. Es müsste alles komplett an WebGL gesendet werden, damit es in einem Zug gezeichnet werden kann. Dies ist vergleichbar mit der Art und Weise, wie wir es mit einem Dreiecksstreifen gemacht hätten. Da wir aber die Dreiecke in ihrer Gesamtheit spezifizieren, anstatt jedes Dreieck einfach durch das Hinzufügen eines einzelnen Punktes zum vorherigen zu definieren, macht es mehr Sinn die Farben pro Seite festzulegen. Die sauberste Art und Weise zu programmieren hat den Vorteil, dass eine neue Funktion mit der Bezeichnung drawElements eingeführt werden kann. Deshalb werden wir im Folgenden diese Methode anwenden.

Der erste Schritt besteht darin, die Puffer welche die Vertexpositionen und Farben des Würfels enthalten, die wir in initBuffers erstellen werden mit den entsprechenden Attributen zu verknüpfen genau wie bei der Pyramide.

Copy to Clipboard

Der nächste Schritt ist das Zeichnen der Dreiecke. Es gibt hier ein kleines Problem. Betrachten wir dke Vorderseite. Wir haben vier Vertexpositionen dafür und jeder von ihnen hat eine zugeordnete Farbe. Es muss jedoch mit zwei Dreiecken gezeichnet werden und da wir einfache Dreiecke verwenden, die ihre eigenen, individuell spezifizierten Eckpunkte benötigen statt Dreiecksstreifen, die Eckpunkte teilen können, müssen wir insgesamt sechs Eckpunkte angeben. Aber wir haben nur vier davon in unserem Array-Puffer.

Was wir tun möchten, ist so etwas wie ein Dreieck zu zeichnen, welches aus den ersten drei Ecken des Array-Puffers besteht und dann ein weiteres Dreieck aus dem ersten, dritten und vierten Eckpunkt zu zeichnen. Damit hätten wir unsere Vorderseite gezeichnet. Das Zeichnen des restlichen Würfels wäre ähnlich. Und genau das werden wir im Folgenden tun.

Dazu verwenden wir etwas, das als Element-Array-Puffer bezeichnet wird und einen neuen Aufruf drawElements. Genauso wie die Array-Puffer, die wir bisher verwendet haben, wird der Array-Puffer mit entsprechenden Werten in initBuffers gefüllt. Zudem wird dieser eine Liste von Knoten mit einem nullbasierten Index in den Arrays enthalten, die wir für die Positionen und die Farben verwendet haben.

Um es zu benutzen, machen wir den Elementpuffer von unserem Würfels zum aktuellen Puffer. Anschließend generieren wir den normalen Code, um unsere Model-View- und Projektionsmatrizen bis zur Grafikkarte zu schieben und rufen drawElements auf, um die Dreiecke zu zeichnen:

Copy to Clipboard

Das wars für drawScene. Der Rest des Codes befindet sich in initBuffers und ist ziemlich offensichtlich. Wir definieren Puffer mit neuen Bezeichnungen, um die neuen Arten von Objekten widerzuspiegeln mit denen wir es zu tun haben werden. Zusätzlich fügen wir einen neuen Puffer für den Vertex-Index-Puffer des Würfels hinzu:

Copy to Clipboard

Wir setzen Werte in den Vertex-Positionspuffer der Pyramide für alle Flächen ein mit einer entsprechenden Änderung der Anzahl der Elemente:

Copy to Clipboard

…ebenso wie für den Vertex-Color-Puffer der Pyramide:

Copy to Clipboard

… und einen für den Vertex-Positionspuffer des Würfels:

Copy to Clipboard

Der Farbpuffer ist ein wenig komplexer, da wir eine Schleife verwenden um eone Liste von Vertexfarben zu erstellen. Auf diese Weise muss nicht jede Farbe viermal für jeden Vertex angegeben werden.

Copy to Clipboard

Schließlich definieren wir den Element-Array-Puffer den Unterschied im ersten Parameter zu:

Copy to Clipboard

Denken Sie daran, dass jede Zahl in diesem Puffer ein Index in der Vertex-Position und Farbpuffer ist. Die erste Linie, kombiniert mit der Anweisung Dreiecke in drawScene zu zeichnen bedeutet, dass wir ein Dreieck mit den Eckpunkten 0, 1 und 2 erhalten und dann ein weiteres mit 0, 2 und 3. Da beide Dreiecke die gleiche Farbe haben und nebeneinander liegen ergibt sich ein Quadrat mit den Eckpunkten 0,1,2 und 3. Nun müssen Sie diesen Vorgang für alle Gesichter des Würfels wiederholen und Voila – sie sind fertig.

Nun wissen Sie, wie man WebGL-Szenen mit 3D-Objekten erstellt und Sie wissen, wie Sie die Verticles, die Sie in Array-Puffern angegeben haben wiederverwenden können, indem Sie Element-Array-Puffer und DrawElemente verwenden.