Come animare la trama dell'acqua 2d top down astratta?


24

Attualmente implemento un gioco con una vista dall'alto in basso sull'oceano. Uso il seguente, una piccola trama astratta:inserisci qui la descrizione dell'immagine

La trama reale è trasparente, ho aggiunto il colore verde per chiarezza.

Il problema che ho ora è che non so come animare questa trama in modo che l'acqua abbia un bell'aspetto. Ho cercato di spostare la texture con un'onda peccato texture.y += sin(angle). Ovviamente ora l'intera trama si sta muovendo, il che sembra un po 'irrealistico. La prossima cosa che ho provato è di aggiungere un altro livello e implementare un effetto di parallasse. In modo che anche i riflessi sotto la superficie dell'acqua si muovessero, ma molto più lentamente. Sembra un po 'meglio, ma non ancora ... abbastanza carino.

Penso che l'animazione più bella sarebbe, se le singole celle si espandessero e si contraggessero, un po 'come una rete o un pezzo di stoffa. Immagina se qualcuno tirasse leggermente verso un vertice di queste celle e la cella vicina si espandesse e la cellula verso cui tiro verso (o spingendo) si contrarrà. Un po 'come una rete di molle (?). Ma non ho idea di come implementare qualcosa del genere:

  • Qual è il modello matematico per questo? Qualcosa con le molle, dove le forze spingono / tirano?
  • E se è così, come posso mappare questo modello sulla trama data? Mantenere tutte le curve e cosa no ...

(Sono anche aperto a diverse idee / risposte su come animare la trama data. Il realismo non è il punto qui, solo un po 'di acqua dall'aspetto gradevole come i movimenti ...)

Soluzione di DMGregory

Ho pubblicato un esempio di libgdx in questo post: l'animazione dell'acqua 2d è frastagliata e non liscia (vedi risposta sul filtro delle trame)

Risposte:


41

Un modo comune per farlo è usare una ricerca di trama indiretta nello shader per distorcere la trama di visualizzazione:

GIF animate che mostrano l'animazione dell'acqua

Qui sto usando una trama con un po 'di rumore di colore a bassa frequenza (piastrellatura di chiazze lisce di colori casuali) e la faccio scorrere attraverso la geometria del display nel tempo.

inserisci qui la descrizione dell'immagine

Invece di disegnare i colori da questa trama, prendo invece i canali rosso e verde e li sottraggo 0.5fper trasformarli in un vettore 2D pseudocasuale che cambia senza problemi nel tempo e nello spazio.

Posso quindi aggiungere un piccolo multiplo di questo vettore alle mie coordinate UV, prima di campionare dalla trama principale dell'acqua. Questo sposta la parte della trama che stiamo leggendo e visualizzando, deformandola.

Calcolando in media due campioni da questo rumore, scorrendo in direzioni opposte, possiamo nascondere la direzione del movimento in modo che appaia come una scarica senza scopo.

In Unity lo shader dovrebbe apparire così: dovrebbe essere abbastanza semplice da tradurre nella lingua dello shader che preferisci:

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
Sembra davvero carino. Non sono sicuro di aver compreso tutti gli attributi: _NoseScale = scalare per ridimensionare la "mappa del rumore". _NoiseScrollVelocity = Vector2 a quale velocità ci muoviamo attraverso la mappa del rumore. _Noise =?. _Distortion = Scalare Ho scelto come fattore di distorsione? v2f = Vertice determiniamo il colore. i =?
morpheus05,

_Noiseè [un campionatore di trame che legge da] la piccola trama casuale blobby sopra. v2f isono i dati interpolati dal vertex shader - usiamo principalmente per ottenere le coordinate della texture per pixel che sta disegnando, i.uv. E hai esattamente ragione su tutto il resto.
DMGregory

Ho implementato lo shader e in qualche modo non funziona (non si muove o la distorsione è troppo grande), presumo di non aver impostato correttamente i valori. time = la differenza dall'ultimo frame in ms. noise_scale = 1 (Uso la trama, ripeti la modalità avvolgimento) noise_scroll_velocity = [0,01, 0,01] distorsione = 0,02
morpheus05

Si noti che la variabile si chiama Time, non DeltaTime. Se usi una differenza nel tempo e il tuo framerate è coerente, otterrai sempre lo stesso numero e eseguirai nuovamente lo shader con gli stessi input, ottenendo lo stesso output (nulla si muove). Peggio ancora, se il tuo framerate è incoerente, otterrai vibrazione avanti e indietro. Si desidera che sia trascorso il tempo totale, non il tempo delta.
DMGregory

A breve ho colpito invia l'ho capito e ora funziona quasi. L'animazione sembra accendere le onde dall'angolo in basso a destra e, dopo circa 10 secondi, svanisce, come le onde che si fermano. Quale potrebbe essere la ragione di ciò?
morpheus05,

6

Questo è chiamato effetto caustico e la generazione di questi effetti in fase di runtime richiede abbastanza tempo, quindi tradizionalmente viene eseguita con l'animazione fotogramma per fotogramma pre-renderizzata. Esistono strumenti che generano frame di animazione caustici per te, come Caustics Generator , che ha una versione gratuita per uso non commerciale. Ci sono anche alcuni pre-made che è possibile acquistare a un prezzo significativamente più economico rispetto alla versione pro dello strumento che ho citato.

Si noti che gli effetti caustici di solito sono anche effetti applicati come un biscotto leggero su un terreno sottomarino o sulla superficie sottomarina. Cioè, metterlo sulla superficie dell'acqua mentre si guarda in basso non è normalmente l'aspetto dell'acqua.


Questo è molto interessante, darò un'occhiata anche a questo generatore (anche se proverò la variante shader se la capisco ...)
morpheus05

4

Sembra una trama che potresti generare da un grafico voronoi, ad esempio:

inserisci qui la descrizione dell'immagine

È possibile apportare piccole e regolari regolazioni al grafico spostando i punti; ridisegnare il grafico ogni fotogramma sarebbe piuttosto costoso, quindi probabilmente vorrai pre-renderizzare l'animazione.


4
In realtà ho reso caustiche in questo modo in uno shader in passato. Non è necessariamente costoso come si potrebbe pensare ( ecco un esempio di rendering dei bordi Voronoi in tempo reale in uno shader WebGL ), sebbene ottenere la giusta forma liscia sui bordi - piuttosto che i poligoni appuntiti - può essere impegnativo.
DMGregory

Ooo, è molto carino; Ho alcuni generatori di terreno per i quali sarebbe molto utile.
FacticiusVir

0

Esiste un metodo oldschool, che prevede un livello di trama inferiore e due trame semitrasparenti per la riflessione in alto.

Se vuoi andare fino in fondo e vuoi che l'acqua non appaia piena di onde clonate o samish blue soupmaps, le mappe di flusso sono l'obiettivo.

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


3
Sebbene i link possano essere d'aiuto, non danno mai risposte valide. Potresti espandere entrambi questi metodi? Come sarebbe andare a implementarlo?
Vaillancourt

Il primo metodo è fondamentalmente un metodo molto vecchio usato per animare l'acqua: si prende una trama dell'acqua di strato base le cui coordinate UVW vengono spostate nella direzione scelta. Ora applichi in aggiunta una normale mappa / bump-map che sposti in un'altra direzione - se fatto bene, questo sembra convincente per i piccoli fiumi. È molto limitato, tuttavia, per grandi specchi d'acqua, poiché qualsiasi cosa che assomigli alle onde avrà l'effetto moiré. Il link spiega l'uso di flowmap molto meglio di quanto potrei.
Pica,

Si prega di utilizzare la funzione di modifica per migliorare la domanda con ciò che è stato aggiunto qui :) Le persone vengono utilizzate per cercare risposte nel post, non nei commenti.
Vaillancourt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.