Dies ist der zweite Teil unserer Einführung in WebGL Shader. Wenn Sie Teil 1 oder unsere Einführung in three.js nicht gelesen haben sollten, werden Sie den Ausführungen hier nicht folgen können, so dass Sie sich zunächst mit diesen Inhalten beschäftigen sollten.

Im letzten Artikel waren wir soweit gekommen, eine rosa Kugel zu generieren, was schon mal ein guter Start in die Welt der Shader ist. Jetzt möchte ich etwas Unterhaltsameres schaffen.

Wir werden ein wenig Zeit damit verbringen, eine Animationsschleife, Vertex-Attribute und eine Uniform hinzuzufügen. Wir fügen auch eine variierende Variable hinzu, so dass der Vertex-Shader einige Daten an den Fragment-Shader senden kann. Das Endergebnis ist, dass unsere rosa Kugel von oben und von der Seite beleuchtet erscheint und pulsiert. Es ist ein bisschen trippig, aber hoffentlich führt es Sie zu einem guten Verständnis der drei Variablentypen sowie deren Beziehung zueinander und der zugrunde liegenden Geometrie. Natürlich werden wir das in three.js einrichten, so dass dies unser bevorzugter Rahmen für diesen Artikel sein wird.

Ein Fake-Licht.

Aktualisieren wir die Farbgebung, damit es kein flaches, schattiertes Objekt ist. Wir könnten einen Blick darauf werfen, wie three.js die Beleuchtung handhabt, aber da ich mir sicher bin, dass es komplexer ist, als wir es jetzt brauchen, werden wir es vortäuschen. Sie sollten sich die fantastischen Shader, die Teil von three.js sind und auch die aus dem aktuellen WebGL-Projekt von Chris Milk und Google ansehen.

Zurück zu unseren Shadern. Wir werden unseren Vertex Shader aktualisieren, um jeden Vertex normal für den Fragment Shadeer bereitzustellen. Dies erfolgt mit einer variierenden Variable:

Copy to Clipboard

Im Fragment Shader werden wir den gleichen Variablennamen einrichten und dann das Punktprodukt des Scheitelpunktes normal mit einem Vektor verwenden, der ein von oben und rechts von der Kugel leuchtendes Licht repräsentiert. Das Ergebnis ist ein Effekt ähnlich einem gerichteten Licht in einem 3D-Paket.

Copy to Clipboard

Der Grund, warum das Punktprodukt funktioniert, ist, dass es bei zwei Vektoren mit einer Zahl ausgegeben wird, die angibt, wie „ähnlich“ die beiden Vektoren sind. Bei normierten Vektoren erhält man, wenn sie genau in die gleiche Richtung zeigen, einen Wert von 1, wenn sie in entgegengesetzte Richtungen zeigen, einen Wert von -1. Wir nehmen diese Zahlen und wenden sie auf unsere Beleuchtung an. Ein Scheitelpunkt oben rechts, hat einen Wert nahe oder gleich 1, d.h. voll beleuchtet, während ein Scheitelpunkt auf der Seite einen Wert nahe 0 hat und auf der Rückseite -1 ist.

Als nächstes legen wir ein paar Scheitelpunkte an.

Attribute.

Was ich jetzt möchte, ist, dass wir über ein Attribut eine Zufallszahl an jeden Scheitelpunkt anhängen. Wir benutzen diese Zahl, um den Scheitelpunkt entlang seiner Normals zu verschieben. Das Ergebnis ist eine Art seltsamer Spike-Ball, der sich jedes Mal ändert, wenn Sie die Seite aktualisieren. Es wird noch nicht animiert sein, aber ein paar Aktualisierungen werden ihnen zeigen, dass es zufällig ist.

Beginnen wir damit, das Attribut zum Vertex-Shader hinzuzufügen:

Copy to Clipboard

Sie werden sehen, dass sich nicht viel geändert hat. Das liegt daran, dass das Attribut in MeshShaderMaterial nicht so effektiv eingerichtet wurde, dass der Shader stattdessen einen Nullwert verwendet. Es ist im Moment so etwas wie ein Platzhalter. In einer Sekunde werden wir das Attribut zum MeshShaderMaterial in JavaScript hinzufügen und three.js wird die beiden für uns automatisch miteinander verbinden.

Bemerkenswert ist auch die Tatsache, dass wir die aktualisierte Position einer neuen vec3-Variablen zuweisen musste, da das ursprüngliche Attribut, wie alle Attribute, nur gelesen wird.

Aktualisierung des MeshShaderMaterials.

Lassen Sie uns direkt in die Aktualisierung unserer MeshShaderMaterial mit dem Attribut gehen, um unser Displacement voranzubringen. Zur Erinnerung: Attribute sind Per-Vertex-Werte, also brauchen wir einen Wert pro Scheitelpunkt in unserer Sphäre und zwar in der folgenden Weise:

Copy to Clipboard

Damit sollten Sie eine verstümmelte Kugel sehen, aber das Coole daran ist, dass die gesamte Verschiebung auf dem Grafikprozessor stattfindet.

Die Animation starten.

Wir sollten das auf jeden Fall animieren. Wie machen wir das? Nun, es gibt zwei Dinge, die wir in Position bringen müssen:

  1. Eine Uniform, um zu animieren, wie viel Verschiebung in jedem Frame angewendet werden soll. Wir können dafür Sinus oder Cosinus verwenden, da sie von -1 bis 1 laufen.
  2. Eine Animationsschleife in JS.

Wir werden die Uniform sowohl dem MeshShaderMaterial als auch dem Vertex Shader hinzufügen. Zuerst der Vertex Shader:

Copy to Clipboard

Unsere Shader sind jetzt fertig. Aber wir scheinen einen Schritt zurück gemacht zu haben. Dies liegt vor allem daran, dass unser Amplitudenwert bei 0 liegt und wir mit dem Displacement multiplizieren, so dass sich nichts ändert. Wir haben auch die Animationsschleife nicht eingerichtet, so dass wir nie sehen, dass sich die 0 zu etwas anderem ändert.

In unserem JavaScript müssen wir nun den Renderaufruf in eine Funktion packen und ihn dann mit requestAnimationFrame aufrufen. Dort müssen wir auch den Wert der Uniform aktualisieren.

Copy to Clipboard

Schlußfolgerungen.

Das wars soweit. Wenn Sie jetzt einen Blick darauf werfen, werden Sie sehen, dass es in einer seltsam pulsierenden Art und Weise animiert. Es gibt so viel mehr, was wir über Shader als Thema behandeln können, aber ich hoffe, Sie haben diese Einführung hilfreich gefunden. Sie sollten jetzt in der Lage sein, Shader zu verstehen, wenn Sie sie sehen und das Vertrauen haben, selbst einige erstaunliche Shader zu erstellen.