Grundlegendes zu Perlin-Rauschen


31

Ich spiele mit Perlin Noise, nachdem ich mit Diamond Square gearbeitet habe. Ich folgte der Implementierung von Hugo Elias , der im Grunde genommen eine Reihe von Funktionen mit x, y als Eingabe erstellt, um jeden Koordinatenwert zu werfen.

Mein PHP Code ist hier :

Ich habe zwei Fragen:

Wie benutze ich den Algorithmus, um eine Höhenkarte in einem Array zu generieren? Ich habe es nicht vollständig verstanden und habe nur den Pseudocode nach PHP portiert, aber die letzte Funktion (map_perlined) ausgeführt, nachdem ich irgendwo gelesen habe, dass der Algorithmus "magisch" Ihnen Übergangswerte für jeden angegebenen x, y-Punkt liefert (anscheinend, ohne dass Sie den Pseudocode lesen müssen) benachbarte Werte), ich bekomme dies nur bei Verwendung als Zufallsfunktionmt_rand(-100,100)/100;

Bildbeschreibung hier eingeben

Und dies bei Verwendung der kryptografischen 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;Methode (welche kann übrigens "wie besehen" in PHP implementiert werden?):

Bildbeschreibung hier eingeben

Zusammenfassend drei Fragen:

  1. Ist mein Code korrekt?
  2. Die Zufallsfunktion kann wie im Code beschrieben nach PHP portiert werden? Es werden keine Fehler ausgegeben, aber die Ergebnisse sind nicht da.
  3. Wie verwende ich den Algorithmus eigentlich?

AKTUALISIEREN

Ok, habe eine PHP-Portierung des in Gustavson Paper gezeigten Codes erstellt, und wie andere Programmierer sagten, erzeugt er nur eine Oktave. Haben Sie eine andere nützliche Seite, ein Dokument oder eine Anleitung, wie Sie diese mit den Konzepten von mehreren Oktaven, Amplitude, Frequenz usw. verwenden können, um die Rauschfunktion zu steuern? Auf Gustavsons Papier werden nur die Ergebnisse angezeigt, nicht die tatsächliche Implementierung des Algorithmus, vielleicht fehlt mir etwas?

UPDATE 2
@NATHAN

Ich habe etwas gemacht wie:

$persistence = 0.5;

for ($j = 0; $j < $size; $j++) {
    for ($i = 0; $i < $size; $i++) {

        for ($o = 0; $o < 8; $o++) {
            $frequency = pow(2,$o);
            $amplitude = pow($persistence, $o);
            $value += SimplexNoise($i*$frequency, $j * $frequency) * $amplitude;
            }

            //$value = SimplexNoise($i, $j) + 0.5 * SimplexNoise($i, $j) + 0.25 * SimplexNoise($i, $j);
            $this->mapArray[$i][$j] = new Cell($value);

Und nachdem ich die Werte auf 0..1 normiert habe, erhalte ich eine ziemlich langweilige Höhenkarte wie:

Bildbeschreibung hier eingeben

Wie setze ich die Map? Vielleicht muss ich in der 3D-Version mit dem dritten Wert eine zufällige Höhe implementieren? Aber wenn ja, müsste ich herausfinden, um Nachbarwerte zu berücksichtigen, die mit so etwas wie einem Diamantquadrat-Algorithmus enden, genau das, was ich nicht tun möchte.

UPDATE 3

Mehr Perlin Arbeit. Ich muss noch einen Weg finden, um das Rauschen zu meinen Ergebnissen zu führen. Überprüfen Sie diese Oktaven und das Endergebnis:

Oktave I bis IV

Octave1Octave2Octave3Octave4

Zusammengefasst

Oktaven 1-4 summiert

Jede Oktave ist ziemlich gleich. Überprüfen Sie den Code:

$persistence = 0.5;

    for ($j = 0; $j < $size; $j++) {
      for ($i = 0; $i < $size; $i++) {
        $value = 0;

        for ($o = 0; $o < 4; $o++) {
          $frequency = pow(2,$o);
          $amplitude = pow($persistence, $o);
          $value += improved_noise($i*$frequency, $j*$frequency, 0.5)*$amplitude;

        }
        $this->map[$i][$j] = new Cell($value);

Die Ergebnisse werden normalisiert. Was würden Sie verwenden, um die Geräuschentwicklung stark zu beeinflussen? Ich sehe Beispiele, bei denen das Ändern der Amplitude weiche oder raue Oberflächen ergibt, aber selbst wenn ich eine große Amplitude gebe, sehe ich wenig Unterschied.


Addieren Sie einfach mehrere Instanzen, indem Sie die Frequenz jedes Mal erhöhen und die Amplitude verringern, wie: Perlin (x) + 0,5 * Perlin (2 * x) + 0,25 * Perlin (4 * x) + ... (für so viele Oktaven wie Sie wollen). Sie können auch versuchen, die Faktoren zu ändern, um ein anderes Aussehen zu erhalten. Sie müssen keine Potenzen von 2 sein.
Nathan Reed

1
Nach dem Update scheinen Sie Y nicht richtig zu skalieren. Ich bin zu müde, um PHP zu lernen (da ich PHP nicht kenne). Bei der ersten Implementierung von Perlin stieß ich jedoch auf ein ähnliches Problem in meiner Muttersprache. Töte auch die Oktaven und debugge nur eine Ebene von Perlin.
Jonathan Dickinson

Jemand für mein III-Update?
Gabriel A. Zorrilla

Antworten:


28

Was Sie implementiert haben, ist kein Perlin-Rauschen. Ich bin mir nicht sicher, warum Hugo Elias das sagt, aber er ist verwirrt. Hier ist die Referenzimplementierung von Ken Perlin. Es ruft eigentlich keinen externen Zufallszahlengenerator auf, sondern verwendet eine eingebaute Hash-Funktion, um die Pseudozufallsgradientenvektoren zu erzeugen.

Beachten Sie auch, dass Perlin-Rauschen nur aus einer Oktave besteht. Das Aufsummieren mehrerer Oktaven (skalierte Instanzen der Rauschfunktion), wie Hugo Elias vorschlägt, ist eine nützliche Technik, aber kein Teil des Perlin-Rauschens. Was Sie dabei erhalten, nennt man fraktales Rauschen, manchmal "fraktales Brownsches Rauschen" (wegen der vermuteten Ähnlichkeit mit der Brownschen Bewegung).

Wenn Sie geometrisch verstehen möchten, was der Algorithmus tut, versuchen Sie dieses Papier . Es handelt sich um eine andere Art von Rauschen, das als "Simplex-Rauschen" bezeichnet wird, enthält jedoch auch eine Erklärung des klassischen Perlin-Rauschens. Übrigens wurde Simplex-Rauschen auch von Perlin erfunden und soll eine Verbesserung gegenüber seinem klassischen Rauschen darstellen. Sie können es also auch implementieren, wenn Sie mit Rauschfunktionen spielen möchten.


2
+1 für die Gustavson-Zeitung. Es erklärt sowohl das Perlin- als auch das Simplex-Rauschen auf die bisher klarste Weise. Offensichtlich Simplex-Geräuschregeln!
FxIII

Ich habe dieses Papier vor einiger Zeit auch gefunden, aber Hugo sah einfacher aus. Ich lese es und probiere es aus! Vielen Dank!
Gabriel A. Zorrilla

2
Vorsicht beim Herunterladen von Simplex-Rauschen, es könnte ein Virus sein;)
Bobobobo

Ich weiß, dass dies ein altes Thema ist, aber zu sagen, dass die Referenzimplementierung keine Zufallszahl verwendet, ist falsch. Bei der Initialisierung der Bibliothek (oder beim ersten Aufruf einer Rauschfunktion) werden 256 zufällige Verläufe erzeugt. Der Hash, auf den Sie sich beziehen, besteht lediglich darin, die unendliche Menge von Ganzzahlen in den zwischengespeicherten Bereich [0, 255] zu zwingen. Dies ist im Wesentlichen nur eine Optimierung für Nachschlagetabellen, und der Algorithmus funktioniert genauso gut, wenn Sie z. B. einen PRNG mit einer Gitterkoordinate ausstatten und diesen zur Erzeugung des Verlaufs verwenden. Auf diese Weise ist er nur (viel) langsamer.
bcrist

@bcrist Ich denke, Sie beziehen sich auf eine ältere Version von Perlin-Rauschen. Perlins "verbessertes Rauschen", mit dem ich verknüpft habe , verwendet einen festen Satz von 12 Gradientenvektoren, nicht 256 zufällige. Es verwendet eine Permutationstabelle als Hash-Funktion, um Gitterkoordinaten auf einen dieser 12 Gradientenvektoren abzubilden.
Nathan Reed

11

Das ist ein weit verbreitetes Missverständnis. Was Hugo Elias "Perlin" -Rauschen nennt, ist in der Tat fraktales oder rosa Rauschen. Um besser zu verstehen, was Perlin-Rauschen ist, können Sie den in Nathan Reeds Antwort verlinkten Artikel von Perlin oder libnoise docs (es gibt den gleichen Fehler: Perlin-Rauschen ist das, was sie als Gradientenrauschen bezeichnen) oder CoherentNoise docs lesen .

Um Ihre Frage tatsächlich zu beantworten: Sie haben das erwartete Ergebnis nicht erhalten, weil die Rauschfrequenz zu hoch ist. Ihre Frequenzen beginnen mit 1 und erhöhen sich, was bedeutet, dass jedes Pixel in der resultierenden Karte einen zufälligen Wert hat. Um eine feinere Struktur der Karte zu sehen, müssen Sie das Rauschen "einzoomen". Ich spreche nicht wirklich PHP, aber ich nehme an, der Code sollte so aussehen:

$arrayMap[$i][$j] = PerlinNoise_2D($i/$width, $j/$height, $p, $octaves);

Das heißt, Sie "strecken" eine Geräuschperiode über Ihre gesamte Karte. Natürlich können Sie auch andere Koeffizienten verwenden - probieren Sie einfach andere aus und sehen Sie, was passiert.


Danke für die kohärenten Lärmdokumente! Ich sehe, dass du es geschrieben hast :) Was ist der Fehler in libnoise docs? Ist Perlin-Rauschen nicht eine Art Gradientenrauschen?
Legends2k
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.