Comprensione del rumore di Perlin


31

Sto giocando con Perlin Noise dopo aver lavorato con Diamond Square. Ho seguito l' implementazione di Hugo Elias che fondamentalmente crea una serie di funzioni con x, y come input per lanciare ogni valore di coordinata.

Il mio codice PHP è qui :

Ho due domande:

Come si usa l'algoritmo per generare una mappa di altezza in un array? Non l'ho capito appieno e ho appena portato su PHP lo pseudocodice, ma facendo l'ultima funzione (map_perlined) dopo aver letto da qualche parte che l'algoritmo "magicamente" ti dà valori di transizione per ogni punto x, y dato (apparentemente, senza dover leggere il suo valori adiacenti), ottengo questo solo quando uso come funzione casualemt_rand(-100,100)/100;

inserisci qui la descrizione dell'immagine

E questo quando si utilizza il crittografico: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(che, a proposito, può essere implementato "così com'è" in PHP?):

inserisci qui la descrizione dell'immagine

Quindi, riassumendo, tre domande:

  1. Il mio codice è corretto?
  2. La funzione casuale può essere trasferita su PHP come descritto nel codice? Non genera errori, ma i risultati non ci sono.
  3. Come uso effettivamente l'algoritmo?

AGGIORNARE

Ok, ha creato una porta PHP del codice mostrato nel documento di Gustavson e, come ha detto un altro programmatore, genera solo un'ottava. Hai qualche altro sito / documento / guida utile su come usarlo con i concetti di ottave multiple, ampiezza, frequenza, ecc. Per controllare la funzione del rumore? Sulla carta di Gustavson mostra solo i risultati, non la reale implementazione dell'algoritmo, forse mi sto perdendo qualcosa?

AGGIORNAMENTO 2
@NATHAN

Ho fatto qualcosa del tipo:

$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);

E dopo aver normalizzato i valori su 0..1, ottengo una mappa di altezza piuttosto noiosa come:

inserisci qui la descrizione dell'immagine

Come si esegue il seeding della mappa? Forse quello che devo implementare è la versione 3d con il terzo valore un'altezza casuale? Ma in tal caso, dovrei scoprire di prendere in considerazione i valori del vicino, che finirei con qualcosa come un algoritmo a diamante quadrato, esattamente ciò che non voglio fare.

AGGIORNAMENTO 3

Più lavoro Perlin. Devo ancora trovare un modo per guidare il rumore verso i miei risultati. Controlla queste ottave e il risultato finale:

Ottava da I a IV

octave1Octave2Octave3Octave4

Riassunto

Ottave 1-4 sommate

Ogni ottava è praticamente la stessa. Controlla il codice:

$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);

I risultati sono normalizzati. Cosa useresti avrebbe una forte influenza nello sviluppo del rumore? Vedo esempi in cui il cambiamento dell'ampiezza dà superfici morbide o ruvide, ma anche se do un'ampiezza enorme, vedo poca differenza.


Basta sommare più istanze, aumentando la frequenza e diminuendo ogni volta l'ampiezza, come: perlin (x) + 0,5 * perlin (2 * x) + 0,25 * perlin (4 * x) + ... (per tutte le ottave tu vuoi). Puoi anche provare a modificare i fattori per ottenere look diversi; non hanno bisogno di essere poteri di 2.
Nathan Reed,

1
Dopo l'aggiornamento, sembra che tu non stia ridimensionando correttamente Y - Sono troppo stanco per grok il PHP (dato che non conosco PHP); ma ho riscontrato un problema simile nella mia lingua madre quando ho implementato perlin la prima volta. Uccidi anche le ottave e esegui il debug di un livello di perlin.
Jonathan Dickinson,

Qualcuno per il mio III aggiornamento?
Gabriel A. Zorrilla,

Risposte:


28

Quello che hai implementato non è il rumore di Perlin. Non sono sicuro del perché Hugo Elias lo dica, ma è confuso. Ecco l'implementazione di riferimento di Ken Perlin. In realtà non chiama alcun generatore di numeri casuali esterno, ma utilizza una funzione hash integrata per produrre vettori di gradiente pseudocasuali.

Si noti inoltre che il rumore di Perlin consiste in una sola ottava. Riassumendo più ottave (istanze ridimensionate della funzione noise), come suggerisce Hugo Elias, è una tecnica utile, ma non fa parte del rumore di Perlin. Ciò che si ottiene facendo questo è chiamato rumore frattale, a volte "rumore browniano frattale" (a causa della presunta somiglianza con il moto browniano).

Se vuoi capire geometricamente cosa sta facendo l'algoritmo, prova questo documento . Riguarda un diverso tipo di rumore chiamato "rumore simplex", ma include anche una spiegazione del rumore classico Perlin. Per inciso, anche il rumore simplex è stato inventato da Perlin e dovrebbe essere un miglioramento rispetto al suo rumore classico, quindi potresti provare a implementarlo anche se sei interessato a giocare con le funzioni del rumore.


2
+1 per il documento di Gustavson. Spiega il rumore sia perlinico che simplex nel modo più chiaro che ho visto finora. Ovviamente regole di rumore simplex!
FxIII,

Ho anche scoperto quel foglio qualche tempo fa, ma Hugo sembrava più semplice. Lo leggerò e lo proverò! Grazie!
Gabriel A. Zorrilla,

2
fai attenzione quando scarichi il rumore simplex, potrebbe avere un virus;)
bobobobo,

So che questo è un vecchio argomento, ma dire che l'implementazione di riferimento non utilizza un numero casuale non è corretto. Quando la libreria viene inizializzata (o la prima volta che viene chiamata una funzione noise) vengono generati 256 gradienti casuali. L'hash a cui ti riferisci è semplicemente quello di forzare l'insieme infinito di numeri interi nell'intervallo [0, 255] memorizzato nella cache. In sostanza si tratta solo di un'ottimizzazione della tabella di ricerca e l'algoritmo funziona altrettanto bene se, ad esempio, si semina un PRNG con una coordinata di griglia e lo si utilizza per generare il gradiente, è solo (molto) più lento in quel modo.
Bcrist

@bcrist Penso che ti riferisci a una versione precedente del rumore di Perlin. Il "rumore migliorato" di Perlin, a cui ho collegato , utilizza un insieme fisso di 12 vettori di gradiente, non 256 casuali. Utilizza una tabella di permutazione come funzione hash per mappare le coordinate della griglia su uno di quei 12 vettori di gradiente.
Nathan Reed,

11

Questo è un malinteso comune. Ciò che Hugo Elias chiama "Perlin" noise è in realtà un rumore frattale o rosa. Per capire meglio cos'è il rumore di Perlin, puoi leggere l'articolo di Perlin collegato nella risposta di Nathan Reed o i documenti di libnoise (c'è lo stesso errore lì: il rumore di Perlin è ciò che chiamano rumore di gradiente) o i documenti di CoherentNoise .

Ora, per rispondere effettivamente alla tua domanda: non hai ottenuto il risultato atteso perché la frequenza del rumore è troppo alta. Le tue frequenze iniziano con 1 e aumentano, il che significa che ogni pixel nella mappa risultante ha un valore casuale. Per vedere la struttura più fine della mappa, è necessario "ingrandire" il rumore. In realtà non parlo PHP, ma suppongo che il codice dovrebbe apparire così:

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

Cioè, "allunghi" un periodo di rumore sull'intera mappa. Certo, puoi usare altri coefficienti: prova solo diversi coefficienti, vedi cosa succede.


Grazie per i coerenti documenti sul rumore! Vedo che l'hai scritto :) Qual è l'errore nei documenti di libnoise? Il rumore di Perlin non è una specie di rumore gradiente?
legends2k
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.