Kunst, die bewegt: Animierte Materialien mit Shader Graph erstellen

In Unity 2018.2 haben wir den Shader Graph um den Input "Vertex Position" erweitert, der es Ihnen ermöglicht, Ihre Meshes anzupassen und zu animieren. In diesem Blogbeitrag zeige ich Ihnen, wie Sie Ihre eigenen Vertex-Animationsshader erstellen können, und gebe Ihnen einige gängige Beispiele wie einen Wind- und einen Wassershader.
Wenn Sie Shader Graph noch nicht kennen, können Sie Tim Coopers Blogbeitrag lesen, um mehr über die wichtigsten Funktionen zu erfahren, oder Sie können sich den Vortrag "Shader Graph Introduction" von Andy Touch auf dem Unity YouTube-Kanal ansehen.
Diese Szene verwendet keine Texturen oder Animationen; alles, was Sie sehen, ist mit Shader Graph gefärbt und animiert.
Shader sind ein unglaublich leistungsfähiger Aspekt der Rendering-Pipeline, der ein hohes Maß an Kontrolle darüber ermöglicht, wie unsere Szenen-Assets dargestellt werden. Mithilfe einer Reihe von Eingaben und Operationen können wir Shader erstellen, die die verschiedenen Rendering-Eigenschaften unserer Assets ändern, z. B. ihre Oberflächenfarbe und -textur und sogar die Scheitelpunktpositionen des Netzes. Sie können auch alle diese Elemente zu komplexen, reichhaltigen Animationen kombinieren. In diesem Blog-Beitrag wird gezeigt, wie Sie mit Vertex-Animationen beginnen können, das Konzept der Verwendung von Masken und Eigenschaften vorgestellt und schließlich erklärt, wie wir die Shader für die Wüsteninsel-Szene erstellt haben.
Repository von GitHub klonen oder .zip von GitHub herunterladen
Laden Sie das Beispielprojekt Desert Island Scene herunter, um selbst mit den Shadern zu experimentieren und zu interagieren! Dieses Projekt enthält alles, was Sie brauchen, um mit Shader Graph zu arbeiten. Stellen Sie sicher, dass Sie das Projekt mit Unity Version 2018.2 oder höher starten.
Jeder Shader in der Desert Island Scene wurde mit dem Gedanken an eine individuelle Anpassung erstellt, also fangen Sie ruhig an, mit den Shader-Werten im Inspector herumzuspielen! Für jedes Objekt gibt es auch eine Voreinstellungsdatei, die die Werte auf die Standardwerte zurücksetzt.
Dieses Werk ist lizenziert unter der Creative Commons Attribution 4.0 International License.
Um Shader Graph verwenden zu können, muss Ihr Projekt die folgenden Anforderungen erfüllen:
- Läuft auf Unity Version 2018.2 oder höher.
- Verwendung der neuen Lightweight- oder High-Definition-Rendering-Pipelines (LWRP wird aufgrund der schnelleren Kompilierungszeiten für Experimente empfohlen).
- Das Paket Shader Graph muss im Paketmanager installiert sein.
Um Shader Graph zu installieren, erstellen oder aktualisieren Sie ein Projekt auf Version 2018.2 oder höher, navigieren Sie zu Fenster > Paketmanager > Alle, suchen Sie Shader Graph in der Liste und klicken Sie auf Installieren.
Wenn Ihre Materialien in der Szenenansicht nicht animiert werden, vergewissern Sie sich, dass Sie Animierte Materialien aktiviert haben:
Etwas Ausgefallenes mit Shader Graph machen?
Sie können eine Vorschau der animierten Materialien anzeigen, indem Sie auf das kleine Bild oben links in der Szenenansicht klicken.
#UnityTips #Unity3D

Bevor wir mit ausgefallener Mathematik Dinge bewegen können, müssen wir erst einmal verstehen, was wir eigentlich bewegen wollen.
Eine Masche in der Szene hat vier Arten von Räumen:
- Object: Scheitelpunktposition relativ zum Netzdrehpunkt.
- Ansicht: Scheitelpunktposition relativ zur Kamera.
- World: Scheitelpunktposition relativ zum Weltursprung.
- Tangente: Für einige spezielle Anwendungsfälle, wie z. B. die Beleuchtung pro Pixel.
Sie können im Dropdown-Menü des Knotens Position auswählen, welchen Bereich Sie beeinflussen möchten.
Mit Hilfe des Split-Knotens können wir auswählen, welche Achse wir beeinflussen wollen.

Der Split-Knoten gibt auf vier Kanälen aus, wobei die ersten drei den Transformationsachsen entsprechen (R=X, G=Y, B=Z). Im obigen Beispiel habe ich die y-Achse des Objekts aufgeteilt und 1 hinzugefügt, wodurch unser Objekt auf seiner eigenen Achse um 1 nach oben verschoben wird.
Manchmal möchten Sie das Objekt im Weltraum bewegen. Wählen Sie dazu im Knoten Position die Option Welt aus und konvertieren Sie dann die Ausgabe mit dem Knoten Transformieren zurück in den Objektraum.
Nachdem wir nun herausgefunden haben, wie man eine Masche bewegt, ist es oft nützlich zu wissen, wie man den Effekt einschränken kann.
Mit Hilfe von Knotenpunkten wie Lerp können wir zwischen zwei Werten überblenden. Der T-Eingang ist der Steuerwert für den Lerp. Wenn unser T-Eingang 0 ist (dargestellt als Schwarz), wird der A-Kanal verwendet. Wenn unsere Eingabe 1 ist (als Weiß dargestellt), wird der B-Kanal verwendet. Im folgenden Beispiel wird der Schieberegler zum Überblenden zwischen den beiden Eingängen verwendet. Jedes der folgenden Beispiele kann anstelle des Schiebereglers verwendet werden.

Mit einer Schwarz-Weiß-Textur können wir detaillierte Formen verwenden, um unser Mesh voranzutreiben. Im obigen Beispiel können Sie sehen, wie Weiß die maximale Höhe unseres Bereichs darstellt, während Schwarz keine Auswirkung auf die Position des Meshes hat. Das liegt daran, dass Schwarz den numerischen Wert 0 hat, und das Hinzufügen von 0 zur Maschenposition führt nicht zu einer Verschiebung.
Um eine Textur mit Scheitelpunktposition zu verwenden, müssen Sie den Knoten Mustertextur 2D LOD anstelle des typischen Knoten Mustertextur 2D verwenden. Texturen sind besonders dann nützlich, wenn Sie eine Maske mit einer einzigartigen Form oder einem bestimmten Grad des Abfalls benötigen.

Ähnlich wie bei einer Texturmaske können Sie bei einer UV-Maske wählen, welchen Teil des Meshes Sie basierend auf der UV-Abwicklung beeinflussen möchten. Im obigen Screenshot verwende ich die u-Achse der UV, um einen Farbverlauf von links nach rechts zu erstellen. Um den Gradienten auszugleichen, verwenden Sie einen Add-Knoten; um die Stärke zu erhöhen, verwenden Sie einen Multiplikationsknoten; und um den Abfall zu erhöhen, verwenden Sie einen Power-Knoten.
Jeder Vertex speichert eine Einheit von Vector3-Informationen, die wir als Vertex-Farbe bezeichnen. Mit dem Poly Brush-Paket können wir direkt im Editor Vertex-Farben malen. Alternativ können Sie auch 3D-Modellierungssoftware (wie 3ds Max, Maya, Blender, 3D Coat oder Modo) verwenden, um Scheitelfarben zuzuweisen. Es ist erwähnenswert, dass die meisten 3D-Modellierungsprogramme Modelle standardmäßig mit dem maximalen RGB-Wert exportieren, der jedem Scheitelpunkt zugewiesen ist.
In der obigen Abbildung ist der Knoten "Scheitelfarbe" in den roten(R) Kanal aufgeteilt und dann mit dem T-Kanal des Knotens " Lerp" verbunden, der als Maske dient. Der A-Kanal des Lerp-Knotens wird verwendet, wenn der Eingang 0 ist, während der B-Kanal verwendet wird, wenn der Eingang 1 ist. In der Praxis wird die obige Einstellung nur dann 1 zur y-Achse hinzufügen, wenn den Scheitelpunkten die rote Scheitelfarbe zugewiesen ist.

Mithilfe des Knotens Normalenvektor können wir eine Eingabe anhand der Ausrichtung der Mesh-Flächen maskieren. Auch hier können wir über den Knoten Split auswählen, welche Achse wir beeinflussen wollen (R=X, G=Y, B=Z). Im obigen Screenshot habe ich die y-Achse als Maske verwendet, so dass nur die nach oben zeigenden Flächen positiv sind. Es ist wichtig, einen Klammerknoten zu verwenden, um alle Werte zu verwerfen, die nicht zwischen 0 und 1 liegen.

Diese Reihe von Knoten verdeckt einen Eingang, wenn die Position des Objekts über der Weltposition 0 auf der y-Achse liegt.

Bei der Erstellung von Shadern kann es schwierig sein, die richtigen Eingabewerte für den gewünschten Effekt zu erhalten. Aus diesem Grund und für die spätere Anpassung mit Prefabs und Presets ist es wichtig, Eigenschaften zu verwenden.
Eigenschaften ermöglichen es uns, die Werte des Shaders zu ändern, nachdem der Shader kompiliert wurde. Um eine Eigenschaft zu erstellen, klicken Sie auf das +-Symbol in der Tafel (rechts abgebildet). Es gibt sechs Arten von Eigenschaften:
- Vektoren (1 bis 4): Eine Zeichenkette von Werten, mit der Option eines Schiebereglers für Vector1.
- Farbe: RGB-Werte mit einem Farbwähler und einer optionalen HDR-Version.
- Texture2D (und Texture2D Array): Ein 2D-Texturbeispiel
- Textur 3D: Ein 3D-Texturbeispiel
- Cubemap: Ein generiertes Cubemap-Beispiel
- Boolesch: Eine Option entweder aus oder ein. Äquivalent zu 0 oder 1.
Der Flaggen-Shader schwenkt eine Sinuswelle im Objektraum über die Flagge, wobei eine UV-Maske verwendet wird, um die linke Seite ruhig zu halten.

Eine UV-Maske, die invertiert und dann mit sich selbst multipliziert wird, um einen gleichmäßigen Farbverlauf über die y-Achse zu erzeugen. Damit wird die Mitte der Flagge vom Ruder weg gebogen.
Es wird eine Sinuswelle aus dem Objektraum erzeugt, deren Amplitude, Frequenz und Geschwindigkeit gesteuert werden kann. Die Welle wird durch eine UV-Maske auf der x-Achse maskiert, um die linke Seite der Fahne ruhig zu halten.
Durch die Ausgabe eines Gradientenrauschens in eine Step-Funktion und dann in den Alpha-Clip-Schwellenwert können wir einige Pixel verwerfen, um die Fahne zu zerreißen.
Der Wind-Shader verwendet Gradientenrauschen im Weltraum, das entlang einer einzigen Achse schwenkt, um die Blätter und das Gras sanft zu schieben und zu ziehen.
Unter Verwendung der Weltposition platzieren wir ein Gradientenrauschen auf der y-Achse und der x-Achse. Mit einem Vector2 können wir die Geschwindigkeit und die Richtung der Verschiebung steuern.
Die Eigenschaften dienen zur Steuerung der Dichte und Stärke des Versatzes. Durch Subtraktion von 0,5 vom Gradientenrauschen wird sichergestellt, dass das Mesh gleichmäßig gedrückt und gezogen wird.
Eine UV-Maske wird verwendet, um die Basis der Blätter und des Grases zu fixieren. Schließlich wird ein Transform-Knoten verwendet, um die Weltposition in die Objektposition umzuwandeln.
Mit diesem Shader berechnen wir den Abstand zwischen der Kamera und der Muschel und verwenden diesen dann als Maske für die Drehung der oberen Hälfte.

Indem wir die Position des Spielobjekts und die Kameraposition in den Knoten Abstand eingeben, können wir eine Maske erstellen. Der Knoten Eins Minus kehrt die Entfernung um, so dass wir einen positiven Wert erhalten, wenn wir uns in der Nähe der Muschel befinden. Der Knoten Clamp verwirft alle Werte über 1 und unter 0.
Diese UV-Maske rotiert nur die Oberseite der Muschel, aber in den meisten Fällen wäre eine Vertex-Farbmaske einfacher und flexibler.
Ein Lerp-Knoten wird verwendet, um zwischen geschlossener und geöffneter Muschel zu wechseln. Die Rotation wird auf die y-Achse und die z-Achse des GameObjects angewendet. Drehen um die x-Achse.
In diesem Shader verwenden wir eine Sinuswelle, die quer zur Achse des Objekts erzeugt wird, um den Fisch zum Wackeln zu bringen. Dann wird der Kopf des Fisches abgeklebt, so dass der Kopf ruhig bleibt.

Erzeugen Sie eine Sinuswelle im Objektraum entlang der y-Achse und der z-Achse, wobei die Eigenschaften die Frequenz und die Geschwindigkeit der Welle steuern.
Da wir sowohl die x-Achse als auch die y-Achse verwenden, wackelt der Fisch in seiner Breite und in seiner Höhe.
Multiplizieren Sie den Ausgang der Sinuswelle, um die Amplitude/Distanz/Stärke des Wobblers zu steuern, und fügen Sie ihn der x-Achse des Objekts hinzu.
Verwenden Sie einen Lerp-Knoten, um die Vorderseite des Fisches über die x-Achse des UV-Kanals zu maskieren. Durch die Verwendung eines Power-Knotens mit einer Eigenschaft können wir den Wobble-Effekt auf den hinteren Teil des Fisches verschieben.
Endlich haben wir den Ozean-Shader! Dieser Shader kompensiert die Oberseite des Meshes mit drei Sinuswellen mit unterschiedlichen Skalen und Winkeln. Diese Sinuswellen werden auch verwendet, um die Farben für die Wellentäler und -spitzen zu erzeugen.

Drei separate Sinuswellen werden im Weltraum erzeugt, wobei jede Eigenschaft zur Steuerung von Amplitude, Frequenz, Geschwindigkeit, Konvergenz und Rotation der Wellen verwendet wird.
Die drei Sinuswellen werden dann mit zwei Add-Knoten kombiniert und mit einem weltweiten Gradienten multipliziert, um die Höhe der Wellenspitzen aufzubrechen. Danach werden die kombinierten Wellen zur Objektposition hinzugefügt.
Zwei Scheitelpunktmasken werden verwendet, um die Wellen zunächst auf den oberen Teil der Kuppel zu beschränken und sie dann wieder nach unten zu schieben, wenn der Schaum aufgemalt wird.

Indem wir die x- und z-Achse aufteilen, erzeugen wir Wellen in zwei Richtungen. Die beiden Multiplikatoren werden verwendet, um den Einfluss der einzelnen Wellen festzulegen. Wird beispielsweise der Z-Kanal mit 0 multipliziert, wird eine Sinuswelle ausschließlich auf der x-Achse ausgegeben.
Wenn man einen World Position-Knoten in die x-Achse und die z-Achse aufteilt und diese dann in einem Vector2 kombiniert, erhält man einen UV-Raum im Weltraum. Dadurch wird das Gradientenrauschen flach in der Welt ausgerichtet. Indem wir diese Ausgabe zur Zeit addieren, verschieben wir die Sinuswellen und helfen so, die ansonsten geraden Linien aufzubrechen.
Der Sinus-Knoten verwendet den Weltraum und die Zeit, um eine einfache Sinuswelle zu erzeugen. Um die Welle spitz zu machen, verwenden wir einen absoluten Knoten, um die negativen Werte zu spiegeln. Der Knoten Eins Minus kehrt diese Werte dann um, so dass die Wellenenden oben liegen.
Wenn Sie wissen möchten, wie Sie mit Shader Graph beginnen können, ist der GDC-Vortrag von Andy Touch ein guter Ausgangspunkt. Wenn Sie nach anderen Shader-Graph-Beispielen suchen, hat Andy auch eine Beispielbibliothek auf GitHub verfügbar.
Eine ausführliche Dokumentation zu Shader Graph, einschließlich Beschreibungen der einzelnen Knoten, finden Sie im Shader Graph Entwickler-Wiki auf GitHub. Diskutieren Sie mit und beteiligen Sie sich an der Diskussion in unserem Forum für experimentelle Grafikvorschauen! Und schließlich, wenn Sie etwas Cooles mit Shader Graph machen, würde ich es gerne sehen! Sie können mich gerne auf Twitter @John_O_Really erreichen.