If you're seeing this message, it means we're having trouble loading external resources on our website.

Wenn du hinter einem Webfilter bist, stelle sicher, dass die Domänen *. kastatic.org und *. kasandbox.org nicht blockiert sind.

Hauptinhalt

Perlin noise

Ein guter Zufallszahlengenerator erzeugt Zahlen, die keine Beziehung haben und kein erkennbares Muster anzeigen. Wie wir allmählich sehen, kann ein wenig Zufall eine gute Sache sein, wenn wir organische, lebensechte Verhaltensweisen programmieren. Allerdings ist Zufall als einziges Leitprinzip nicht notwendigerweise natürlich.
Es gibt einen Algorithmus, der zu natürlicheren Ergebnissen führt, und der ist als "Perlin-Rauschen" bekannt. Ken Perlin entwickelte die Rauschfunktion während seiner Arbeit am Originalfilm Tron in den frühen 1980er Jahren; er verwendete sie, um prozedurale Texturen für computergenerierte Effekte zu erstellen. Im Jahr 1997 gewann Perlin für diese Arbeit einen Academy Award für technische Leistungen. Mit Perlin-Rauschen lassen sich verschiedene Effekte mit natürlichen Eigenschaften erzeugen, z. B. Wolken, Landschaften und gemusterte Texturen wie Marmor.
Perlin-Noise sieht organischer aus, da er eine natürlich geordnete (“Geglättete”) Folge von Pseudo-Zufallszahlen erzeugt. Das Diagramm unten zeigt Perlin-Noise im Laufe der Zeit, wobei die x-Achse für die Zeit steht. Beachte wie die Kurve schön geglättet ist.
Nature of Code Abbildung
Bild I.5: Rauschen
Im Gegensatz, zeigt das nächste  Diagramm unten rein Zufällige Zahlen im Laufe der Zeit.
Nature of Code Abbildung
Bild I.6: Zufall
ProcessingJS verfügt über eine integrierte Implementierung des Algorithmus für Perlin Noise: die Funktion noise(). Die Funktion noise() akzeptiert ein, zwei oder drei Parameter, da das Rauschen in einer, zwei oder drei Dimensionen berechnet wird. Beginnen wir, indem wir uns zuerst eindimensionales Rauschen anschauen.

Details zum Rauschen

Die noise reference sagt uns, dass das Rauschen über mehrere “Oktaven” berechnet wird. Wenn die Funktion noiseDetail() aufgerufen wird, kann damit sowohl die Anzahl der Oktaven als auch ihr gegenseitiges Verhältnis verändert werden.
Zeichnen wir an einer zufälligen x-Position einen Kreis in unserem ProcessingJS-Fenster:
var x = random(0, width);
ellipse(x, 180, 16, 16);
Anstatt nun einfache eine zufällige x-Position zu verwenden, wollen wir eine x-Position mit Perlin-Noise, damit das ganze verhalten "weicher" wird. Du meinst nun vielleicht, wir müssen nur random durch noise() ersetzen, wie z.B.
var x = noise(0, width);
ellipse(x, 180, 16, 16);
Grundsätzlich wollen wir zwar genau dies tun, einen x-Wert mit Perlin-Noise, basierend auf dem Bereich von 0 bis zur Breite. Dies ist aber nicht die korrekte Umsetzung. Während zwar die Parameter der Funktion random() einen Bereich vom Minimum bis zum Maximum definieren, funktioniert noise() etwas anders. Stattdessen erwartet die Funktion noise() einen Parameter welcher einen "Zeitpunkt" darstellt und sie gibt uns immer einen Wert zwischen 0 und 1 zurück.  Wir können uns eindimensionalen Perlin-Noise als eine lineare Sequenz von Werten im Laufe der Zeit vorstellen. Hier ein paar Beispiele von Eingabe und Rückgabwert von Perlin-Noise:
ZeitRauschen
00.469
0.010.480
0.020.492
0.030.505
0.040.517
Um nun auf einen dieser Rauschwerte in ProcessingJS zu verwenden, müssen wir der Funktion noise() einen bestimmten Zeitpunkt übergeben. Zum Beispiel:
var n = noise(0,03);
Gemäss der Tabelle oben gibt noise() zum Zeitpunkt 0.505 den Wert 0.03 zurück. Wir können ein Programm schreiben, welches eine Variable für die Zeit verwendet und in der Funktion draw() laufend den Rauschwert abfragt.
Der Code oben wird immer und immer wieder das gleiche Ergebnis ausgeben. Dies daher, weil wir immer wieder die Funktion noise() mit dem gleichen Wert für den Zeitpunkt aufrufen.
Wenn wir aber die Variable t für den Zeitpunkt hochzählen, erhalten wir immer ein anderes Resultat.
Wie schnell wirt hochzählen beeinflusst die Glättung des Rauschens. Wenn wir große Sprünge in der Zeit machen, springen wir nach vorn und die Werte werden zufälliger.
Rauschen im Laufe der Zeit
Bild 1,7
Führe den Code oben mehrmals aus und zähle t jeweils um 0,01; 0,02; 0,05; 0,1; 0,0001 hoch und du wirst unterschiedliche Resultate sehen.

Das Rauschen abbilden

Jetzt sind wir bereit, die Frage zu beantworten, was wir mit dem Rauschwert tun sollen. Sobald wir den Wert mit einem Bereich zwischen 0 und 1 haben, liegt es an uns, diesen Bereich dem zuzuordnen, was wir wollen.
Wir können ihn einfach mit der oberen Grenze des Bereichs multiplizieren. Aber dies ist gleiche eine gute Gelegenheit um die Funktion map() von ProcessingJS kennenzulernen. Die Funktion map() akzeptiert fünf Parameter. Als erstes den Wert, welchen wir abbilden wollen, in diesem Fall ist dies n. Danach geben wir den Bereich (Minimum und Maximum) des Eingabewertes gefolgt vom Bereich des gewünschten Ausgabewertes an.
Nature of Code Abbildung
Bild I.8
In diesem Fall, wissen wir, dass as Rauschen einen Bereich von 0 bis 1 hat, wir aber ein Rechteck mit einer Breite zwischen 0 und der aktuellen Breite zeichnen wollen.
Wir können die genau gleiche Logik für unseren Random-Walker benutzen und ihm sowohl für x- wie auch y-Wert Perlin-Noise zuweisen.
Beachte, wie das obige Beispiel ein zusätzliches Paar von Variablen erfordert: tx und ty. Das liegt daran, dass wir zwei Zeitvariablen im Auge behalten müssen, eine für die x-Position des Walker Objekts und eine für die y-Position.
Aber da hat es etwas seltsames bei diesen Variablen. Weshalb beginn tx bei 0 und ty bei 10 000? Die Zahlen an sich wurden willkürlich gewählt, aber wir haben aus einem bestimmten Grund für die zwei Variablen zwei verschiedene Startwerte gewählt. Dies daher, weil noise eine deterministische Funktion ist: Sie gibt dir für den gleichen Eingabewert (Zeitpunkt) t immer den gleichen Rückgabewert. Wenn wir sowohl fürx wie y das Rauschen zum gleichen Zeitpunkt t generieren, erhalten x und y immer auch den gleichen Wert und der Walker würde sich immer nur diagonal bewegen. Stattdessen verwenden wir einfach zwei verschiedene Abschnitte des Rausch-Raumes. Wir beginnen bei 0 für x und bei 10000 für y. So verhalten sich x und y unabhängig voneinander.
Nature of Code Abbildung
Bild I.9
In Tat und Wahrheit ist hier gar kein Konzept von Zeit im Spiel. Es ist einfach eine nützliche Metapher welche uns hilft die Funktionsweise der Funktion noise zu verstehen. Wir haben hier eher Raum anstatt Zeit. Das Diagaramm oben zeigt eine lineare Abfolge von Rauschwerten in einem eindimensionalen Raum und wir können jederzeit den Wert einer bestimmte x-Position abfragen. Oft wird zum Beispiel auch die Variable xoff verwendet. Sie steht für x-offset auf dem Rauschdiagramm und wird anstatt t für Zeit (wie im Diagramm gezeigt) verwendet.
In der nächsten Challenge kannst du nun das Perlin-Rauschen und den Walker auf eine leicht andere Weise verwenden. Viel Spass!

Der Kurs "Natürliche Simulationen" ist eine Bearbeitung von "The Nature of Code" von Daniel Shiffman, und wird unter der Creative Commons Attribution-NonCommercial 3,0 Unported Lizenz verwendet.

Willst du an der Diskussion teilnehmen?

Noch keine Beiträge.
Verstehst du Englisch? Klick hier, um weitere Diskussionen auf der englischen Khan Academy Seite zu sehen.