Prozedurale Hydrologie: Dynamische Simulation von Flüssen und Seen

Hinweis: Der vollständige Quellcode des Projekts wird auf Github [ hier ] veröffentlicht. Das Repository enthält außerdem detaillierte Informationen zum Lesen und Verwenden des Codes.

Nach der Implementierung der partikelbasierten hydraulischen Erosionssimulation entschied ich, dass es möglich sein würde, dieses Konzept zu erweitern, um andere Aspekte der Oberflächenhydrologie zu simulieren.

Ich habe die vorhandenen Methoden zur prozeduralen Erzeugung von Flüssen und Seen untersucht, aber die gefundenen Ergebnisse passten nicht zu mir.

Das Hauptziel vieler Methoden ist die Erstellung von Flusssystemen (sehr schön) unter Verwendung verschiedener Algorithmen (manchmal basierend auf einer zuvor erstellten Höhenkarte oder einem inversen Problem), aber es fehlt ihnen eine starke realistische Beziehung zwischen Topographie und Hydrologie.

Darüber hinaus wird die Verarbeitung des Wassermodells auf dem Relief als Ganzes für einige Ressourcen berücksichtigt und eine Simulation hochkomplexer Flüssigkeiten verwendet.

In diesem Artikel werde ich meinen Versuch demonstrieren, diese Probleme mit einer Technik zu überwinden, die die Fähigkeit erweitert, eine partikelbasierte hydraulische Erosion zu simulieren. Ich werde auch erklären, wie ich im Allgemeinen das Problem „Wasser auf dem Relief“ löse.

Bei meiner Methode strebe ich sowohl nach Einfachheit als auch nach Realismus auf Kosten einer geringfügigen Erhöhung der Komplexität des zugrunde liegenden Erosionssystems. Ich empfehle meinen vorherigen Artikel über dieses System zu lesen [ hier , Übersetzung auf Habré], weil das neue Modell auf ihn basiert.


Dieses System ist in der Lage, mit Hydrologie schnell ein sehr realistisch aussehendes Terrain zu erzeugen. Dieses Video wurde in Echtzeit gerendert. Das System ist in der Lage, eine unendliche Anzahl solcher Landschaften zu erzeugen.

Erläuterung: Ich bin kein Geologe, daher habe ich das System basierend auf meinem Wissen erstellt.

Hydrologiekonzept


Ich möchte ein generatives System schaffen, das viele geografische Phänomene simulieren kann, darunter:

  • Fluss- und Bachwanderung
  • Natürliche Wasserfälle
  • Canyon Formation
  • Schwellung des Bodens und der Auen

Folglich müssen die Systeme der Hydrologie und Topographie dynamisch und eng miteinander verbunden sein. Das partikelbasierte hydraulische Erosionssystem hat dafür bereits die grundlegenden Aspekte:

  • Das Relief beeinflusst die Bewegung des Wassers
  • Erosion und Sedimentation beeinflussen das Gelände

Tatsächlich simuliert dieses System die durch Regen verursachte Erosion, kann jedoch nicht viele andere Einflüsse vermitteln:

  • In einem sich bewegenden Strom verhält sich Wasser anders.
  • In einem stehenden Pool verhält sich das Wasser anders

Hinweis: Ich werde oft Streams und Pools erwähnen . Im Modell wird die Annahme getroffen, dass es sich um zweidimensionale Phänomene im großen Maßstab handelt. Sie reduzieren die Komplexität des Modells erheblich.

Die meisten der oben genannten geografischen Phänomene können mithilfe des Modells von Flüssen und Becken vermittelt werden. Idealerweise sollten sie den Realismus eines partikelbasierten Systems ausleihen und verbessern.

Vereinfachtes hydrologisches Modell


Das Speichern von Informationen zu Flows und Pools in einer oder mehreren Datenstrukturen (Grafiken, Objekte usw.) ist zu komplex und schränkt unsere Möglichkeiten ein.

Deshalb besteht unser hydrologisches Modell von zwei Karten: Flusskarten und Becken Karten .

Hinweis: Vergessen Sie nicht, dass sie als 2D-Systeme modelliert sind.

Stream- und Pool-Karten


Die Flusskarte beschreibt das fließende Wasser an der Oberfläche (Bäche und Flüsse). Es speichert die zeitlich gemittelten Partikelpositionen auf der Karte. Alte Informationen werden langsam gelöscht.

Die Beckenkarte beschreibt das stille Wasser an der Oberfläche (Pfützen, Teiche, Seen, Ozeane). Es speichert die Wassertiefe an der entsprechenden Position der Karte.

Hinweis: Stream- und Pool-Maps sind Arrays mit derselben Größe wie die Höhenkarte.


Erleichterung mit hydrologischen Auswirkungen. Die Wasserschicht im Putz stammt aus hydrologischen Karten.


Kombinierte hydrologische Karten. Hellblau ist eine Stream-Karte, Dunkelblau ist eine Pool-Karte.

Diese Karten werden durch Partikel erzeugt und verbunden, die Wasser entlang des Geländes bewegen. Durch Hinzufügen dieser hydrologischen Karten erhalten wir auch zeitunabhängige Informationen, die die Interaktion von Partikeln mit ihrer Simulation separat ermöglichen. Durch die Verwendung dieser Karten können Partikel interagieren, um Parameter zu erhalten, die ihre Bewegung beeinflussen.

Hinweis: Die Stream-Map wird nach dem Durchlaufen der Easy-In-Out-Funktion angezeigt und auf dieser Grundlage auf dem Gelände gerendert. Um feinere / schärfere Flüsse zu erzielen (oder niedrigere Werte in weiten flachen Bereichen zu ignorieren), kann diese Anzeige geändert oder Schwellenwerte dafür festgelegt werden.

Wasser als Partikel


Wasser wird in Form einer diskreten Masse („Partikel“) mit einem Volumen präsentiert, die sich entlang der Oberfläche des Reliefs bewegt. Es hat mehrere Parameter, die seine Bewegung beeinflussen (Reibung, Verdunstungsrate, Ablagerungsrate usw.).

Dies ist die grundlegende Datenstruktur zur Simulation der Hydrologie. Partikel werden nicht gespeichert , sondern nur für die Interaktion zwischen Karten von Höhen, Flüssen und Pools verwendet.

Hinweis: Das Konzept eines Partikels wurde in einem früheren Beitrag [ Übersetzung auf Habré] (und einer unendlichen Anzahl anderer Ressourcen) ausführlicher erläutert .

Hydrologische Zyklus- und Karteninteraktion


Karten interagieren über einen Wasserkreislauf miteinander. Der Wasserkreislauf besteht aus folgenden Schritten:

  • Erstellen eines Partikels im Gelände
  • (.. ).
  • , .
  • , .
  • , ( ) .
  • .

Im gesamten System gibt es nur zwei Algorithmen: Abstieg (Abstieg) und Überschwemmung (Überflutung) . Absteigende Partikel verändern die Karte der Strömungen, und überflutete Partikel verändern die Karte der Becken. Diese Algorithmen werden nachstehend ausführlich beschrieben.


Eindimensionales Diagramm des hydrologischen Modells. Partikel werden im Gelände erzeugt und zyklisch von zwei Algorithmen verarbeitet: Abstieg und Flut. Dabei ändern sich die Karten der Becken und Flüsse, was sich wiederum auf die Bewegung der Partikel auswirkt.

Implementierung


Im Folgenden werde ich die vollständige Implementierung des Systems zur Generierung der Ergebnisse erläutern und Codebeispiele vorstellen.

Hinweis: Ich werde nur relevante Codeteile anzeigen. Weitere Informationen finden Sie im Repository auf Github. Alle relevanten Teile des Codes befinden sich in der Datei „water.h“.

Partikelklasse


Die Struktur des Tropfenpartikels ist identisch mit der Struktur des vorherigen Systems. Abstieg und Flut sind jetzt Mitglieder der Struktur, da sie jeweils nur auf ein Partikel wirken.

struct Drop{
  
  //... constructors

  int index;                         //Flat Array Index
  glm::vec2 pos;                     //2D Position
  glm::vec2 speed = glm::vec2(0.0);
  double volume = 1.0;
  double sediment = 0.0;

  //... parameters
  const double volumeFactor = 100.0; //"Water Deposition Rate"

  //Hydrological Cycle Functions
  void descend(double* h, double* stream, double* pool, bool* track, glm::ivec2 dim, double scale);
  void flood(double* h, double* pool, glm::ivec2 dim);
};

Ein zusätzlicher Parameter ist der Volumenfaktor, der bestimmt, wie die Überschwemmung das Volumen auf den Wasserstand überträgt.

Abstiegsalgorithmus


Der Abstiegsalgorithmus ist fast der gleiche wie der einfache Partikelerosionsalgorithmus. Er erhält zusätzliche Eingabe "Track" - ein Array, in das er alle von ihm besuchten Positionen schreibt. Ein Array wird benötigt, um in Zukunft Stream-Maps zu erstellen.

void Drop::descend(double* h, double* stream, double* pool, bool* track, glm::ivec2 dim, double scale){

  glm::ivec2 ipos; 

  while(volume > minVol){

    ipos = pos; //Initial Position
    int ind = ipos.x*dim.y+ipos.y; //Flat Array Index

    //Register Position
    track[ind] = true;

    //...
  }
};

Der Parametersatz wird durch Fluss- und Poolzuordnungen geändert:

//...
  //Effective Parameter Set
  double effD = depositionRate;
  double effF = friction*(1.0-0.5*stream[ind]);
  double effR = evapRate*(1.0-0.2*stream[ind]);
//...

Hinweis: Ich habe herausgefunden, dass eine solche Parameteränderung gut funktioniert.

Im vorherigen System konnten Partikel aus diesem Kreislauf herauskommen und nur bei vollständiger Verdunstung oder über die Grenzen des Reliefs hinaus zerstört werden. Jetzt wurden hier zwei zusätzliche Ausstiegsbedingungen hinzugefügt:

//... nind is the next position after moving the particle
  
  //Out-Of-Bounds
  if(!glm::all(glm::greaterThanEqual(pos, glm::vec2(0))) ||
     !glm::all(glm::lessThan((glm::ivec2)pos, dim))){
       volume = 0.0;
       break;
  }

  //Slow-Down
  if(stream[nind] > 0.5 && length(acc) < 0.01)
    break;

  //Enter Pool
  if(pool[nind] > 0.0)
    break;

//...

Wenn das Partikel keine ausreichende Beschleunigung aufweist und von anderen Partikeln umgeben ist oder direkt in den Pool gelangt, schließt es den Abstieg mit seinem gesamten verbleibenden Volumen vorzeitig ab und fährt mit dem Flutungsalgorithmus fort.

Hinweis: Durch die Überlaufbedingung wird auch das Volumen zurückgesetzt, sodass die Partikel nicht zum Flutungsalgorithmus übergehen.

Hochwasseralgorithmus


Ein Partikel mit dem verbleibenden Volumen kann aus seiner aktuellen Position fluten. Dies geschieht, wenn es nicht mehr abfällt (es gibt keine Beschleunigung) oder in einen vorhandenen Pool gelangt.

Der Flutungsalgorithmus überträgt das Volumen des Partikels auf den erhöhten Wasserstand und ändert die Karte des Beckens. Die Technik besteht darin, den Wasserstand mithilfe der „Testebene“ schrittweise um einen Bruchteil des Partikelvolumens zu erhöhen. Mit steigendem Wasserstand nimmt das Partikelvolumen ab.


Überflutungsalgorithmus-Animation. Die Testebene und der Wasserstand steigen allmählich an, wodurch das Partikelvolumen verringert wird. Wenn ein Leck gefunden wird, bewegt sich das verbleibende Volumen zum Leckpunkt, um den Abstieg durchzuführen.

Bei jedem Schritt führen wir eine Flutfüllung von der Position des Partikels aus durch (dh überprüfen Sie rekursiv die Positionen der Nachbarn) und fügen alle Positionen über der ursprünglichen Ebene (aktueller Wasserstand) und unter der Testebene zum „Flutsatz“ hinzu. Dies ist der Reliefbereich, der Teil des Pools ist.

Während des Füllens prüfen wir auf Lecks. Dies sind Punkte aus dem Satz von Überschwemmungen, die unterhalb der Testebene UND der ursprünglichen Ebene liegen. Wenn wir mehrere Leckstellen finden, wählen wir die niedrigste aus.

void Drop::flood(double* height, double* pool, glm::ivec2 dim){

  index = (int)pos.x*dim.y + (int)pos.y;
  double plane = height[index] + pool[index];  //Testing Plane
  double initialplane = plane;                 //Water Level

  //Flood Set
  std::vector<int> set;
  int fail = 10; //Just in case...

  //Iterate while particle still has volume
  while(volume > minVol && fail){

    set.clear();
    bool tried[dim.x*dim.y] = {false};

    //Lowest Drain
    int drain;
    bool drainfound = false;

    //Recursive Flood-Fill Function
    std::function<void(int)> fill = [&](int i){

      //Out of Bounds
      if(i/dim.y >= dim.x || i/dim.y < 0) return;
      if(i%dim.y >= dim.y || i%dim.y < 0) return;

      //Position has been tried
      if(tried[i]) return;
      tried[i] = true;

      //Wall / Boundary of the Pool
      if(plane < height[i] + pool[i]) return;

      //Drainage Point
      if(initialplane > height[i] + pool[i]){

        //No Drain yet
        if(!drainfound)
          drain = i;

        //Lower Drain
        else if( pool[drain] + height[drain] < pool[i] + height[i] )
          drain = i;

        drainfound = true;
        return; //No need to flood from here
      }

      //Part of the Pool
      set.push_back(i);
      fill(i+dim.y);    //Fill Neighbors
      fill(i-dim.y);
      fill(i+1);
      fill(i-1);
      fill(i+dim.y+1);  //Diagonals (Improves Drainage)
      fill(i-dim.y-1);
      fill(i+dim.y-1);
      fill(i-dim.y+1);
    };

    //Perform Flood
    fill(index);

    //...

Hinweis: Der Einfachheit halber wird hier ein Acht- Wege-Füllalgorithmus verwendet . In Zukunft wird es möglich sein, es effizienter umzusetzen.

Nachdem wir die vielen Überschwemmungs- und Leckstellen identifiziert haben, ändern wir den Wasserstand und die Poolkarte.

Wenn ein Leckpunkt gefunden wird, bewegen wir das Partikel (und sein Überlaufvolumen) zum Leckpunkt, damit es wieder abfallen kann. Dann sinkt der Wasserstand auf die Höhe der Leckstelle.

    //...

    //Drainage Point
    if(drainfound){

      //Set the Particle Position
      pos = glm::vec2(drain/dim.y, drain%dim.y);

      //Set the New Waterlevel (Slowly)
      double drainage = 0.001;
      plane = (1.0-drainage)*initialplane + drainage*(height[drain] + pool[drain]);

      //Compute the New Height
      for(auto& s: set) //Iterate over Set
        pool[s] = (plane > height[s])?(plane-height[s]):0.0;

      //Remove some sediment
      sediment *= 0.1;
      break;
    }

    //...

Hinweis: Wenn der Wasserstand aufgrund von Leckagen abnimmt, habe ich festgestellt, dass dies bei einer geringen Leckrate am besten funktioniert. Darüber hinaus hilft die Entfernung eines Teils des Sedimentgesteins bei der Umsetzung.

Aus diesem Grund bewegen neue Partikel, die in den gefüllten Pool gelangen, ihr Volumen sofort zum Leckpunkt, da durch Hinzufügen von Volumen zum Pool das gleiche Volumen verdrängt wird.

Wird der Leckpunkt nicht gefunden, berechnen wir das Volumen unter der Testebene und vergleichen es mit dem Volumen des Partikels. Wenn es weniger ist, entfernen wir das Volumen aus dem Partikel und stellen den Wasserstand ein. Dann steigt die Testebene. Wenn es größer ist, wird die Testebene abgesenkt. Der Vorgang wird wiederholt, bis das Partikel keinen Platz mehr hat oder eine Leckstelle gefunden wird.

    //...

    //Get Volume under Plane
    double tVol = 0.0;
    for(auto& s: set)
      tVol += volumeFactor*(plane - (height[s]+pool[s]));

    //We can partially fill this volume
    if(tVol <= volume && initialplane < plane){

      //Raise water level to plane height
      for(auto& s: set)
        pool[s] = plane - height[s];

      //Adjust Drop Volume
      volume -= tVol;
      tVol = 0.0;
    }

    //Plane was too high and we couldn't fill it
    else fail--;

    //Adjust Planes
    float approach = 0.5;
    initialplane = (plane > initialplane)?plane:initialplane;
    plane += approach*(volume-tVol)/(double)set.size()/volumeFactor;
  }

  //Couldn't place the volume (for some reason)- so ignore this drop.
  if(fail == 0)
    volume = 0.0;

} //End of Flood Algorithm

Die Höhe der Ebene wird proportional zu der Volumendifferenz eingestellt, die durch die Oberfläche des Pools (d. H. Durch die Größe des Satzes) skaliert wird. Durch Verwendung des Näherungskoeffizienten können Sie die Stabilität erhöhen, mit der das Flugzeug den richtigen Wasserstand erreicht.

Erosionsfolie


Die Weltklasse enthält alle drei Karten in Form gewöhnlicher Arrays:

class World {

public:
  void generate();            //Initialize
  void erode(int cycles);     //Erode with N Particles

  //...

  double heightmap[256*256] = {0.0};
  double waterstream[256*256] = {0.0};
  double waterpool[256*256] = {0.0};

};

Hinweis: Die Höhenkarte wird mit Perlin-Rauschen initialisiert.

Jeder hydrologische Schritt für ein einzelnes Partikel besteht aus Folgendem:

//...

//Spawn Particle
glm::vec2 newpos = glm::vec2(rand()%(int)dim.x, rand()%(int)dim.y);
Drop drop(newpos);

int spill = 5;
while(drop.volume > drop.minVol && spill != 0){

  drop.descend(heightmap, waterstream, waterpool, track, dim, scale);

  if(drop.volume > drop.minVol)
    drop.flood(heightmap, waterpool, dim);

  spill--;
}

//...

Der Überlaufparameter bestimmt, wie oft ein Partikel in den Pool eindringen und ihn wieder verlassen kann, bevor es einfach zerstört wird. Andernfalls sterben die Partikel ab, wenn ihr Volumen erschöpft ist.

Hinweis: Partikel gelangen selten in die Pools und verlassen sie mehr als ein oder zwei Mal, bevor sie während der Abstiegsphasen vollständig verdunsten. Ich habe dies jedoch nur für den Fall hinzugefügt.

Die Erosionsfunktion umschließt diesen Code und führt hydrologische Schritte für N Partikel durch, wobei die Flusskarte direkt geändert wird:

void World::erode(int N){

  //Track the Movement of all Particles
  bool track[dim.x*dim.y] = {false};

  //Simulate N Particles
  for(int i = 0; i < N; i++){
   
    //... simulate individual particle

  }

  //Update Path
  double lrate = 0.01;  //Adaptation Rate
  for(int i = 0; i < dim.x*dim.y; i++)
    waterstream[i] = (1.0-lrate)*waterstream[i] + lrate*((track[i])?1.0:0.0);

}

Hier wird das Spurarray an die Abstiegsfunktion übergeben. Ich fand heraus, dass die gleichzeitige Verfolgung der Bewegung mehrerer Partikel und entsprechende Änderungen verbesserte Ergebnisse für die Flusskarte liefern. Die Anpassungsrate bestimmt, wie schnell alte Informationen gelöscht werden.

Bäume


Nur zum Spaß habe ich Bäume hinzugefügt, um zu sehen, ob die Erosionssimulation weiter verbessert werden kann. Sie werden im Weltklassenzimmer als Vektor gespeichert.

Bäume werden zufällig auf der Karte an Orten erstellt, an denen es keine Pools und starken Bäche gibt und das Gelände nicht sehr steil ist. Sie haben auch die Möglichkeit, zusätzliche Bäume um sich herum zu erstellen.

Bei der Erstellung von Bäumen schreiben sie in einem bestimmten Radius um sie herum auf die Dichtekarte der Vegetation. Eine hohe Vegetationsdichte verringert den Stoffübergang zwischen absteigenden Partikeln und Topographie. Dies soll simulieren, wie die Wurzeln den Boden an Ort und Stelle halten.

//... descend function
double effD = depositionRate*max(0.0, 1.0-treedensity[ind]);
//...

Bäume sterben, wenn sie sich im Pool befinden oder der Bach unter ihnen zu stark ist. Darüber hinaus haben sie eine zufällige Wahrscheinlichkeit des Todes.


Dank Schattierung und normalen Karten machen selbst sehr einfache Baumsprites das Relief schöner.

Hinweis: Das Baummodell befindet sich in der Datei "vegetation.h" und in der Funktion "World :: grow ()".

Andere Details


Die Ergebnisse werden mit einem hausgemachten OpenGL-Wrapper visualisiert, der [ hier ] angelegt ist.

Ergebnisse


Auf der Karte können Partikel entsprechend der von Ihnen benötigten Verteilung erstellt werden. In meinen Demos habe ich sie mit einer gleichmäßigen Verteilung auf 256 × 256 Karten erstellt.

Wie unten zu sehen ist, hängt die resultierende Simulation stark von der Wahl des ursprünglichen Reliefs ab. Das System kann eine Vielzahl von Naturphänomenen simulieren. Ich konnte nicht nur Canyons angemessen bekommen. Sie benötigen möglicherweise eine sehr lange und langsame Simulation.

Andere Phänomene können im System beobachtet werden, wie Wasserfälle, Tortuosität und Flussdeltas, Seen, Bodenschwellungen und so weiter.

Das System ist auch sehr gut darin, Flüsse und Pools an Orten zu verteilen, an denen sich viel Regen ansammelt, und nicht an zufälligen Orten. Daher ist die erzeugte Hydrologie eng mit dem Gelände verbunden.


Hydrologische Echtzeitsimulation auf einem 256 × 256-Gitter. Das ursprüngliche Relief ist relativ glatt, wodurch Streams schnell erscheinen können. Ganz am Anfang kann man die einfachste Entstehung von Pools und Lecks beobachten, wonach große Ströme auftreten und verbleiben.

Vergleich der Auswirkungen der Verengung von Strömungen


Um den Unterschied zu vergleichen, der durch die Verknüpfung einer Karte mit einem Erosionssystem entsteht, können Sie die Hydrologie auf derselben Karte simulieren und verschiedene Effekte ein- und ausschalten.

Ich habe das gleiche Gelände dreimal simuliert:

  • Partikelbasierte Erosion (Grunderosion), die Fluss- und Poolkarten erhält. Pools wirken sich immer noch auf die Generierung aus
  • Grundlegende Erosion mit Parametern, die durch hydrologische Karten geändert wurden (in Kombination mit Erosion)
  • Kombinierte Erosion mit Parametern, die durch hydrologische Karten geändert wurden und die Erosion durch Bäume beeinflussen

Hinweis: Dies ist ein ziemlich chaotisches System, und die Art der Hydrologie hängt stark vom Gelände ab. Es ist schwierig, ein "sehr aufschlussreiches" Beispiel für eine Erleichterung zu finden.


Relief-Rendering des Basissystems


Kombiniertes Rendern der Systemhöhe


Darstellung der Topographie eines Systems mit Bäumen

Eine interessante Beobachtung: Die Kombination hydrologischer Karten mit Partikelparametern verengt tatsächlich die Flussbetten. Insbesondere in planaren Regionen sind Partikel weniger verteilt und verschmelzen zu einer kleinen Menge stärkerer Strömungen.

Reduzierte Reibung und Verdunstung bewältigen erfolgreich die Tatsache, dass Partikel bereits vorhandene Kanäle bevorzugen.

Andere Effekte sind bei direkter Beobachtung des Reliefs sichtbarer.


Hydrologische Karte des Basissystems


Hydrologische Karte des kombinierten Systems


Hydrologische Karte des Systems mit Bäumen

Hinweis: Diese Ergebnisse wurden in genau 60 Sekunden der Simulationszeit generiert.

Bäume wirken sich zusätzlich auf die Verengung aus. Sie verbessern das Ausschneiden klarer Wege in steilen Bereichen. Sie zwingen die Ströme, in den bereits verlegten Kanälen zu bleiben, und verringern so die Tortuosität. Somit beeinflusst die Lage der Bäume die Bewegung des Wassers.


Ein Beispiel für die Aufzeichnung, wie die Position von Bäumen dazu beitragen kann, die Position von Streams beizubehalten. Dies ist die gleiche Erleichterung wie zuvor, mit allen aktivierten Effekten.

Auswirkungen auf den Pool


Das System zum Erstellen von Pools funktioniert gut und ermöglicht das Vorhandensein mehrerer Gewässer mit unterschiedlichen Höhen auf demselben Relief. Sie können auch ineinander übergehen und sich entleeren.


Ein Beispiel für ein Video der Bildung von Pools auf einem gröberen Grundlinienrelief mit einem großen Höhenunterschied. Der obere See befindet sich physisch über dem unteren und leitet das entstehende Wasser direkt in den unteren See ab.

Hinweis: Ich habe mehrere Samen erhalten, in denen drei Seen nacheinander ineinander flossen, aber ich wollte nicht viel Zeit damit verbringen, den richtigen für diesen Artikel zu finden. Ich habe bereits zu viele Bilder und Videos generiert.

Von Zeit zu Zeit springt die Höhe des Pools. Ich denke, dies passiert, wenn der Wasserstand nahe an der Leckage liegt und viel Wasser hinzugefügt wird. Dieser Effekt kann durch Verringern der Leckrate in der Flutungsfunktion verringert werden.


Nach einer weiteren Minute der Generierung erschienen mehrere neue Pools für sich.


In einem steileren Winkel ist der Unterschied in den Beckenhöhen deutlicher.


Die hydrologische Karte zeigt deutlich, dass das zentrale Becken in das untere Becken übergeht.

Die Ausführung des Flooding-Algorithmus führt dazu, dass die Pools am Rand der Karte eine "Wand" sehen. Dies macht sich in den oben gezeigten Bildern bemerkbar.

Eine weitere mögliche Verbesserung könnte die Hinzufügung des Meeresspiegels zur Welt sein, so dass die Pools Lecks an den Rändern der Karte auf Meereshöhe beobachten, andernfalls laufen sie einfach über.

Simulationsgeschwindigkeit


Die Zeit jedes Abstiegs- und Flutungsschritts variiert von Partikel zu Partikel, es verbleibt jedoch etwa eine Größenordnung (etwa 1 Mikrosekunde). Bei stetigen Flüssen bewegen sich Partikel schneller auf der Karte.

Die Überflutungszeit variiert proportional zur Größe des Pools, da der Gießvorgang der teuerste Schritt ist. Je größer die Pools sind, desto größer ist der Bereich, für den Sie den Wasserstand erhöhen müssen. Große Pools sind definitiv der Engpass des Systems. Wenn Sie Ideen zur Geschwindigkeitssteigerung haben, lassen Sie es mich wissen.

Die Abstiegszeit variiert proportional zur Größe der Karte und vielen anderen Parametern, einschließlich Reibung und Verdunstungsrate.

Alle Videos in diesem Artikel werden in Echtzeit aufgezeichnet, dh die Simulation ist im Allgemeinen schnell.

Hinweis: Kurz nach der Veröffentlichung dieses Artikels habe ich die Methode zur Berechnung von Oberflächennormalen geringfügig geändert, wodurch die Simulationsgeschwindigkeit erhöht wurde. Der Effekt ist während der Simulation sehr deutlich, aber es ist schwierig, ihn zu bewerten, da die Zeit zum Starten und Fluten sehr unterschiedlich ist. Nach meinen Schätzungen hat sich die Simulationsgeschwindigkeit verdoppelt.

Weitere schöne Videos



Hydrologiesimulation auf unebenem vertikalem Gelände.


Eine etwas sanftere Erleichterung. Einige Seen schwanken ein wenig.

Hydrologiesimulation auf flachem, glattem Gelände.

Nachfolgende Videos wurden nach Geschwindigkeitsverbesserung aufgenommen.


Noch flacher und glatteres Gelände.


Video mit einem Fluss aus mehreren verbundenen Bächen. Der Hauptfluss hat zwei Punkte, an denen er kleinere Flüsse enthält, und wir sehen, wie er an Größe zunimmt.


Eine ungleichmäßigere Erleichterung bei der Bildung von Flüssen.

Ich kann für immer weitermachen.

Fazit und Arbeit für die Zukunft


Diese einfache Technik basiert immer noch auf Partikeln, schafft es jedoch erfolgreich, viele zusätzliche Effekte zu vermitteln. Es bietet eine einfache Möglichkeit, Wasserbewegungen in großem Maßstab zu simulieren, ohne die Fluiddynamik vollständig zu simulieren. Außerdem arbeitet sie mit einem intuitiven Wassermodell.

In den Simulationen können wir die Entstehung von gewundenen Flüssen, Wasserfällen, Seen und Transfusionen von Seen, Flüssen, die sich in flache Gebiete in Deltas teilen, usw. beobachten.

Es wäre interessant, verschiedene Bodentypen in Form einer Bodenkarte hinzuzufügen, aus der Erosionsparameter entnommen werden könnten.

Sie können das Baumsystem auch einfach ändern, um verschiedene Baumarten zu erstellen, die den Boden an Ort und Stelle halten.

Es ist schwierig, die Vielfalt der generierten Ergebnisse in mehreren Bildern und Videos zu vermitteln. Sie sollten also versuchen, es selbst zu tun. Es stellt sich als sehr interessant heraus. Ich empfehle, mit den ursprünglichen Kartenparametern zu experimentieren, einschließlich Oktavrauschen und Kartenmaßstab.

Wenn Sie Fragen oder Kommentare haben, können Sie mich kontaktieren. Ich habe ziemlich hart an diesem Projekt gearbeitet, also hat mein Gehirn gesintert und ich bin sicher, dass ich einige interessante Aspekte übersehen habe.

All Articles