Acqua di calcolo della GPU che scorre


15

Ho un background di ingegneria civile ed eseguo regolarmente analisi idrauliche e idrologiche. Vendono lauree per quel genere di cose, ma in realtà non è scienza missilistica. Recentemente mi è venuto in mente di implementare l'intero processo idrologico e idraulico per un terreno sulla GPU. Ho appreso shader di calcolo solo di recente, quindi attualmente sono bloccato a essere più bravo in ingegneria che a progettare flussi di lavoro GPU paralleli.

Puoi calcolare la quantità di acqua generata durante un evento di pioggia usando la formula:
Q (CF/S) = c * I (in/hr) * A (acres)

Ho difficoltà ad andare oltre il calcolo della "superficie" anche della prima area.

Panoramica attuale dell'attuazione:

  1. Il terreno è una griglia regolare di vertici a intervalli di 1 unità
  2. Una heightmap contiene un valore di altezza R32 per ciascun vertice
  3. Attualmente, consento il flusso solo nelle 4 direzioni cardinali (senza diagonali)
  4. Sto usando un Texture2D [int] come uno stencil per i vertici che ho già analizzato

Algoritmo corrente:

  1. Quando lo strumento terreno è stato attivo e ora non lo è ....
  2. Cancella lo "stencil".
  3. Scansiona l'intero terreno per la quota più bassa.
  4. Quel singolo punto è l'input iniziale per CS_Flood.
  5. CS_Flood effettua un passaggio sull'asse X.
  6. Ogni vertice di input viene proiettato nelle direzioni X e X + fino a 2048 volte.
  7. Trovare un vertice adiacente con una coordinata OOB indica il bordo del terreno in questa direzione. CurrentPoint viene aggiunto al buffer BoundaryPoints e il ciclo di proiezione per quella direzione viene terminato. È stato facile e funziona sempre bene.
  8. Vertici adiacenti con altezze> = l'altezza del vertice corrente sono contrassegnati nello stencil e aggiunti al buffer NextPass.
  9. Vertici adiacenti con altezze <l'altezza del vertice corrente indica il picco di una cresta e termina il circuito di proiezione. Una futura iterazione del riempimento di inondazione potrebbe scorrere intorno alla base della cresta, lungo il lato "posteriore" di esso e rilevare la stessa cresta una seconda volta.
  10. Qualsiasi punto di picco / cresta che viene rilevato più di una volta non sarà un BoundaryPoint, a questo scopo.
  11. Qualsiasi punto di picco / cresta rilevato esattamente una volta viene aggiunto a BoundaryPoints e il circuito di proiezione in quella direzione viene terminato.
  12. CS_Flood esegue un passaggio dell'asse Z con lo stesso codice, utilizzando come input i punti generati dal passaggio dell'asse X.
  13. Al momento, CS_Flood continua a alternare indefinitamente tra le due direzioni. Alla fine, terminerò il ciclo generale ogni volta che CS_Flood viene completato e il buffer NextPass è vuoto.

Idealmente, a quel punto, BoundaryPoints conterrebbe ogni vertice che si verifica sulla divisione del drenaggio naturale. Le gocce d'acqua che atterrano all'interno del confine alla fine scorrono nello stesso punto basso. Le gocce d'acqua che atterrano al di fuori del confine vanno "altrove".

Poi:

  1. Senza cancellare lo stencil, ripetere la scansione del terreno per il vertice più basso, non stencil.
  2. Iterate CS_Flood.
  3. Ripeti fino a quando lo stencil è pieno (o qualcosa di simile).

Il 3D è difficile da percepire con questi colori; questo mostra le curve di livello alle quote integrali:
(un buco circondato da un berme vicino al bordo) foro del bordo

Esistono circa 10 modi unici per drenare attraverso un vertice; dando a ciascuno un colore unico si presenta come:
(segni circolari visibili, "creste" si presentano bene) inserisci qui la descrizione dell'immagine

Questo mostra ogni punto generato da CS_Flood, confine o altro, come POINTLIST: inserisci qui la descrizione dell'immagine

L'algoritmo funziona quasi sempre . A volte funziona anche correttamente. Altre volte, l'algoritmo è chiaramente contenuto nella forma corretta ma continuerà a generare punti indefinitamente. Come visto nel terzo screenshot, a volte viene confuso. Ci deve essere un'altra situazione / fattore che ho trascurato. Gradirei qualsiasi aiuto per trovare la mia supervisione o suggerimenti su modi più semplici e / o più eleganti per attaccare il problema.

punto mancante

MissingPoint! può essere incluso aiutando la banda dell'algoritmo per aggiungere ogni nuovo BoundaryPoint rilevato al buffer NextPass. Durante il passaggio successivo, il 99% dei punti generati da tale cerotto perderà una piccola quantità di tempo GPU determinando che non possono andare da nessuna parte e non fare nulla. Durante il primo passaggio, l'invio di LowestPoint insieme agli altri punti NextPass gestirà anche questo scenario specifico.

So che è plausibile e, dato il tempo sufficiente, sarò in grado di aiutarlo abbastanza da fare quello che voglio. Mi piacerebbe farlo in un modo migliore, più intelligente, più veloce, se possibile, e non ho ancora abbastanza esperienza per conoscerlo meglio.


Quindi vuoi dire che vuoi solo calcolare dove viene scaricata tutta l'acqua nel terreno?
EvilTak

@EvilTak, penso di aver optato per un buon algoritmo, ma sto ancora ottenendo "cose ​​strane" che non ho l'esperienza per spiegare. Se sei bravo in GPU parallele, dai un'occhiata a: gamedev.stackexchange.com/questions/118556/…
Jon

Risposte:


1

Quando una goccia "ha provato" a visitare un vertice, lo stencil è stato contrassegnato con l' InterlockedExchangeutilizzo del "valore originale" per determinare se era già stato stencil (anche se l'ho appena sovrascritto).

Il miglior algoritmo che ho escogitato ha dato al diluvio un "blocco per appunti" e una sola regola: "non scorrere in discesa" (altezze uguali o superiori). Ciò ha eliminato quasi tutti i test complicati. Sebbene sia generalmente bravo a non fluire su picchi / creste, scorre lungo di essi perché i vertici adiacenti sono "piatti". Questo a volte permette alle gocce di sgattaiolare oltre le creste.

inserisci qui la descrizione dell'immagine

Ciascuno dei punti "troppo lontani" viene quindi "fluito" e scorrerà "nell'area di drenaggio (si ferma a 1) oppure no (si ferma a 0). I "nots" vengono scartati e il blocco per appunti corretto viene copiato nel "final". Se la finale è già stampigliata, il blocco appunti viene scartato. (Futuro: tali collisioni dovrebbero rappresentare collettivamente il limite esterno dell'attuale area di drenaggio.)

A 10FPS:

inserisci qui la descrizione dell'immagine

I "nots" sono mostrati in rosso, una volta che la grande area è copiata nella finale e diventa verde, quindi l'algoritmo si ripete per le restanti aree non definite.

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.