Wie animiere ich eine abstrakte 2D-Top-Down-Wassertextur?


24

Ich implementiere derzeit ein Spiel mit einem Top-Down-Blick auf den Ozean. Ich benutze folgende, ein wenig abstrakte Textur:Bildbeschreibung hier eingeben

Die eigentliche Textur ist transparent, ich habe der Klarheit halber die grünliche Farbe hinzugefügt.

Das Problem, das ich jetzt habe, ist, dass ich nicht weiß, wie ich diese Textur animieren soll, damit das Wasser schön aussieht. Ich versuchte , die Textur mit einer Sinuswelle zu bewegen: texture.y += sin(angle). Natürlich bewegt sich jetzt die gesamte Textur, was irgendwie unrealistisch aussieht. Als nächstes habe ich versucht, eine weitere Ebene hinzuzufügen und einen Parallaxeeffekt zu implementieren. Damit würden sich auch Reflexionen unter der Wasseroberfläche bewegen, allerdings viel langsamer. Es sieht ein bisschen besser aus, aber immer noch nicht ... nett genug.

Ich denke, die am besten aussehende Animation wäre, wenn sich die einzelnen Zellen ausdehnen und zusammenziehen würden, wie ein Netz oder ein Stück Stoff. Stellen Sie sich vor, jemand würde an einem Scheitelpunkt dieser Zellen leicht ziehen und die benachbarte Zelle würde sich ausdehnen und die Zelle, zu der ich ziehe (oder die ich drücke), würde sich zusammenziehen. Ein bisschen wie ein Federnnetz (?). Aber ich habe keine Ahnung, wie ich so etwas implementieren soll:

  • Was ist das Mathe-Modell dafür? Etwas mit Federn, wo Kräfte drücken / ziehen?
  • Und wenn ja, wie ordne ich dieses Modell der angegebenen Textur zu? Alle Kurven behalten und was nicht ...

(Ich bin auch offen für verschiedene Ideen / Antworten, wie man die gegebene Textur animiert. Hier geht es nicht um Realismus, sondern nur um ein paar gut aussehende Bewegungen, die wie Wasser aussehen ...)

Lösung von DMGregory

Ich habe in diesem Beitrag ein libgdx-Beispiel gepostet: 2D-Wasseranimation ist gezackt und nicht glatt (siehe Antwort zur Texturfilterung)

Antworten:


41

Eine übliche Methode ist die Verwendung einer indirekten Texturensuche im Shader, um die Anzeigetextur zu verzerren:

Animiertes GIF mit Wasseranimation

Hier verwende ich eine Textur mit niederfrequentem Farbrauschen (Kacheln von glatten Blobs mit zufälligen Farben) und bewege sie über die Anzeigegeometrie im Laufe der Zeit.

Bildbeschreibung hier eingeben

Anstatt die Farben von dieser Textur zu zeichnen, nehme ich stattdessen die roten und grünen Kanäle und subtrahiere sie 0.5f, um sie in einen pseudozufälligen 2D-Vektor zu verwandeln, der sich über Zeit und Raum hinweg reibungslos ändert.

Ich kann dann ein kleines Vielfaches dieses Vektors zu meinen UV-Koordinaten hinzufügen, bevor ich von der Hauptwassertextur eine Probe nehme. Dies verschiebt den Teil der Textur, die wir lesen und anzeigen, und verzieht ihn.

Durch Mitteln von zwei Abtastwerten aus diesem Geräusch, die in entgegengesetzte Richtungen scrollen, können wir die Bewegungsrichtung verbergen, so dass es wie zielloses Schwappen aussieht.

In Unity würde der Shader so aussehen - er sollte einfach genug sein, um in die Shader-Sprache Ihrer Wahl übersetzt zu werden:

fixed4 frag (v2f i) : SV_Target
{               
    float2 waveUV = i.uv * _NoiseScale;
    float2 travel = _NoiseScrollVelocity * _Time.x;

    float2 uv = i.uv;
    uv += _Distortion * (tex2D(_Noise, waveUV + travel).rg - 0.5f);
    waveUV += 0.2f; // Force an offset between the two samples.
    uv += _Distortion * (tex2D(_Noise, waveUV - travel).rg - 0.5f);

    // Sample the main texture from the distorted UV coordinates.
    fixed4 col = tex2D(_MainTex, uv);

    return col;
}

1
Das sieht wirklich gut aus. Ich bin nicht sicher, ob ich alle Attribute verstehe: _NoseScale = Skalar zum Skalieren der "Noise Map". _NoiseScrollVelocity = Vector2 Mit welcher Geschwindigkeit bewegen wir uns über die Rauschkarte. _Noise =? _Distortion = Scalar Ich wähle als Verzerrungsfaktor? v2f = Vertex wir bestimmen die Farbe. i =?
morpheus05

_Noiseist [ein Textur-Sampler, der aus] der oben genannten kleinen blöden zufälligen Textur. v2f isind die interpolierten Daten aus dem Vertex - Shader. Wir verwenden sie hauptsächlich, um die Texturkoordinaten für das Pixel zu ermitteln, das wir zeichnen i.uv. Und im Übrigen liegen Sie genau richtig.
DMGregory

Ich habe den Shader implementiert und irgendwie funktioniert er nicht (er bewegt sich nicht oder die Verzerrung ist zu groß). Ich gehe davon aus, dass ich die Werte nicht richtig eingestellt habe. Zeit = die Differenz zum letzten Frame in ms. noise_scale = 1 (ich verwende deine Textur, wiederhole den Wrap-Modus) noise_scroll_velocity = [0.01, 0.01] distortion = 0.02
morpheus05

Beachten Sie, dass die Variable Time heißt und nicht DeltaTime. Wenn Sie einen Zeitunterschied verwenden und Ihre Framerate konstant ist, erhalten Sie immer die gleiche Nummer und Sie führen den Shader mit den gleichen Eingaben erneut aus und erhalten die gleiche Ausgabe (nichts bewegt sich). Schlimmer noch, wenn Ihre Framerate inkonsistent ist, werden Sie hin und her vibrieren. Sie möchten die abgelaufene Gesamtzeit und nicht die Deltazeit.
DMGregory

Bald ist es soweit und ich habe gemerkt, dass es fast funktioniert. Die Animation scheint Wellen aus der unteren rechten Ecke zu erzeugen, und nach etwa 10 Sekunden wird sie nur ausgeblendet, wie Wellen, die aufhören. Was könnte der Grund dafür sein?
morpheus05

6

Dies wird als ätzender Effekt bezeichnet, und das Erzeugen dieser Effekte zur Laufzeit ist ziemlich zeitaufwendig. Daher wird dies traditionell mit vorgerenderten Einzelbildanimationen durchgeführt. Es gibt Tools, die ätzende Animationsrahmen für Sie erstellen , wie z. B. Caustics Generator , der eine kostenlose Version für nichtkommerzielle Zwecke enthält. Es gibt auch einige vorgefertigte, die Sie für deutlich günstigere Preise als die von mir erwähnte Pro-Version des Tools kaufen können.

Beachten Sie, dass ätzende Effekte in der Regel auch ein Effekt sind, der als leichter Keks auf einem Unterwassergelände oder auf der Unterwasseroberfläche angewendet wird. Das heißt, es auf die Oberfläche des Wassers zu legen, während man hineinschaut, ist normalerweise nicht so, wie Wasser aussieht.


Das ist sehr interessant, ich habe auch einen Blick auf diesem Generator (Ereignis aber ich werde die Shader - Variante versuchen , wenn ich es sehe ...)
morpheus05

4

Dies sieht aus wie eine Textur, die Sie aus einem Voronoi-Diagramm generieren könnten, z.

Bildbeschreibung hier eingeben

Sie können kleine, sanfte Anpassungen am Diagramm vornehmen, indem Sie die Punkte verschieben. Das erneute Zeichnen des Graphen in jedem Frame ist sehr teuer. Daher möchten Sie die Animation wahrscheinlich vorab rendern.


4
Ich habe in der Vergangenheit diese Art von Ätzmitteln in einem Shader gerendert. Es ist nicht unbedingt so teuer, wie Sie vielleicht denken ( hier ist ein Beispiel, wie Voronoi-Kanten in einem WebGL-Shader in Echtzeit gerendert werden ), obwohl es schwierig sein kann, die richtige glatte Form an den Kanten zu erzielen, anstatt spitze Polygone.
DMGregory

Oh, das ist sehr schön. Ich habe einige Geländegeneratoren, für die das sehr praktisch wäre.
FacticiusVir

0

Es gibt eine Oldschool-Methode, die eine untere Texturebene und zwei halbtransparente Texturen für die Reflexion darüber umfasst.

Wenn Sie den ganzen Weg gehen möchten und das Wasser nicht voller geklonter Wellen oder samischblauer Suppen aussehen soll, sind Flowmaps das richtige Ziel.

https://steamcdn-a.akamaihd.net/apps/valve/2010/siggraph2010_vlachos_waterflow.pdf


3
Obwohl Links helfen können, geben sie keine guten Antworten. Könnten Sie beide Methoden erläutern? Wie würde die Implementierung aussehen?
Vaillancourt

Bei der ersten Methode handelt es sich im Grunde genommen um eine sehr alte Methode zum Animieren von Wasser. Sie verwenden eine Basisschicht-Wassertextur, deren UVW-Koordinaten in die Richtung Ihrer Wahl verschoben werden. Jetzt wendest du zusätzlich eine normale Map / Bump-Map an, die du in eine andere Richtung verschiebst - wenn du das gut machst, sieht das für kleine Flüsse überzeugend aus. Es ist jedoch für große Gewässer sehr begrenzt, da alles, was Wellen ähnelt, einen Moiré-Effekt hat. Der Link erklärt die Verwendung von Flowmaps viel besser als ich es könnte.
Pica

Bitte benutze die Bearbeitungsfunktion, um die Frage mit dem, was du hier hinzugefügt hast, zu verbessern.
Vaillancourt
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.