WebGL - 3D im Browser

siehe auch WebGPU!
 Home
 WebGL Api Spickzettel
 WebGL Sicherheit

Tutorial
 0 : WebGL Browser
 1 : Das erste Dreieck
 2 : 3D-Mathematik
 3 : Farbe
 4 : Animation
 5 : Interaktion I
 6 : Texturen
 7 : Beleuchtung I
 8 : Interaktion II

Links
 WebGL Beispiele
 WebGL Frameworks
 ext. WebGL Tutorials


 Kontakt / Impressum
 webgl ([ät)] peter-strohm Punkt de

4 Animation

>>>> Direkt zum Beispiel <<<<

4.1 Was bedeutet Animation für den Programmablauf?

Was ist der wesentliche Unterschied zwischen den vorhergehenden Beispielen und Animation? Bisher hat es ausgereicht, einmalig das Objekt zu zeichnen. Es wurde mit Vertices und Farben konfiguriert und bleibt dann für alle Ewigkeit oder bis zum nächsten Mausklick unverändert.
Animation bedeutet, dass sich die Darstellung mit der Zeit verändert oder anders ausgedrückt: Die Szene wird mit veränderten Eigenschaften mehrfach nacheinader gezeichnet.

Wiedermal muss ich dir eventuell vorhandene Illusionen nehmen: In WebGL gibt es keine Funktion rotate() oder ähnliches. Wir müssen zunächst einmal alles selbst programmieren - und können damit auch alle Aspekte der Animation selbst bestimmen.

4.2 Immer wieder - nur anders

So sieht's aus:
drehendes Dreieck

Bild 4.1 : Screenshot zum Beispiel 4

Fangen wir mit dem einfachen Teil an: Javascript stellt uns die Funktion setInterval(funktion, Millisekunden) zur Verfügung. Diese sorgt dafür, dass eine andere Funktion, wiederholt im angegebenen Zeitinterval zyklisch aufgerufen wird.

Update 15.2.2011: setInterval ist böse

Mit gutem Grund wird in den WebGL-FAQs dringend empfohlen, die neue (browserabhängige) Funktion requestAnimationFrame zu verwenden. Im Gegensatz zu setInterval wird hiermit die Szene nur dann neu gerendert, wenn sie auf dem Bildschirm sichtbar ist. Der Browser "weiß" wenn z.B. ein anderer Tab oder ein anderes Fenster die 3D-Animation überlagert und kann in diesem Fall den Rechenaufwand einsparen.
Die Browserabhängigkeit bei requestAnimationFrame ist auch in soweit gelöst, dass freundliche Programmierer von Google einen Wrapper geschrieben haben, der browserunabhängig funktioniert und (unter Beachtung der Lizenzbestimmungen) in eigenen Projekten verwendet werden kann. webgl-utils.js enthält den browserunabhängigen Wrapper für requestAnimationFrame und wird mit dem <include>-Tage am Beginn von kapitel4.html eingebunden.

Ich weise so deutlich auf die Unterschiede zwischen setInterval und requestAnimationFrame da in vielen WebGL-Beispielen im Netz noch die Zeile setInterval("drawScene(gl)",40) oder ähnlich verwendet wird. Das ist aus Performance-Gründen ausdrücklich nicht zu empfehlen.

Wie der Name bereits verrät, geschieht in requestAnimationFrame das Entscheidende für die Animation. Als Parameter werden die Zeichnungsfläche (meineCanvas) und die für jeden Frame aufzurufende Funktion (renderLoop übergeben. Dadurch entsteht eine gewollte(!) Endlosschleife. Die eigentliche Render-Funktion drawScene wird erst danach aufgerufen.
Wir könnten natürlich die Transformation (Winkel- und Positionänderung) ebenfalls in drawScene implementieren. Dann wären die Geschwindigkeiten der Bewegung allerdings von der Leistung der Grafikkarte etc. abhängig. Stattdessen verwenden wir hierfür (und nur hierfür) setInterval: nextFrame wird alle 40ms aufgerufen und verändert Position und Drehwinkel des Dreiecks etwas. Dann wird das Dreieck mit diesen neuen Parameter neu gezeichnet wenn der Browser auf requestAnimationFrame reagiert.

Wir erreichen mit dieser Vorgehensweise, dass
1. die Animation "flüssig" dargestellt wird (ohne sichtbares Ruckeln).
2. die Position und Rotation von der Zeit abhängen (z.B. eine Umdrehung pro Sekunde, 1m/s, etc..) und nicht von der Darstellungsgeschwindigkeit des Systems/der Grafikkarte.

4.3 Modifikation der Modelview Matrix

Wie ich in Kapitel 2 beschrieben habe, können wir sämtliche Translationen und Rotationen unserer 3D-Objekte in einer einzigen Matrix zusammenfassen: der Modelview-Matrix.
Die Neuerung in drawScene() in diesem Kapitel ist die dreistufige Transformation der Modelview-Matrix.
In den Zeilen 97-102 des Quellcodebeispiels wird

1. eine Z-Translation um -5.0 Einheiten in die Modelview-Matrix integriert (wie in vorherigen Kapiteln).

2. eine X-Translation um die Variable fAnimationXPos integriert (der Wert der Variablen wird in nextFrame berechnet

3. eine Rotation um die Y-Achse um fAnimationYAngle Grad eingebaut. In dieser Zeile hilft wiedermal sylvester.js mit der Berechnung der Rotationsmatrix und dem Vektor der Rotationsachse.

Das war es auch schon mit den Grundlagen der Animation. Der Rest des Beispielquellcodes bleibt im Vergleich mit Kapitel 3 unverändert.
Du kannst mit der Animation experimentieren, indem du z.B. die Geschwindigkeiten von Rotation und Translation veränderst (Zeilen 117 + 118), die Rotationsachse veränderst oder statt der Cosinus-Funktion eine andere Funktion für die Translation einbaust.
Was passiert wenn du in drawScene die Reihenfolge der Multiplikation der Modelview-Matrix mit Translations- und Rotationsmatrix vertauschst ?

<< Kapitel 3 <<    >> Startseite <<   ^ Seitenanfang ^     >> Kapitel 5 >>
Fehler? Kommentare? webgl ([ät)] peter-strohm Punkt de