Comprendre le bruit de Perlin

31

Je joue avec Perlin Noise après avoir travaillé avec Diamond Square. J'ai suivi l' implémentation par Hugo Elias qui, fondamentalement, crée une série de fonctions avec x, y en entrée pour lancer chaque valeur de coordonnée.

Mon code PHP est ici :

J'ai deux questions:

Comment utiliser l'algorithme pour générer une carte de hauteur dans un tableau? Je ne l'ai pas bien compris et j'ai simplement porté en PHP le pseudocode, mais en faisant la dernière fonction (map_perlined) après avoir lu quelque part que l'algorithme vous "magiquement" vous donne des valeurs de transition pour chaque point x, y donné (apparemment, sans avoir à lire son valeurs adjacentes), je reçois juste ceci lors de l'utilisation comme fonction aléatoiremt_rand(-100,100)/100;

entrez la description de l'image ici

Et ceci lors de l'utilisation de la cryptographie: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(qui, BTW, peut être implémenté "tel quel" en PHP?):

entrez la description de l'image ici

Donc, en résumé, trois questions:

  1. Mon code est-il correct?
  2. La fonction aléatoire peut être portée en PHP comme décrit dans le code? Il ne génère aucune erreur, mais les résultats ne sont pas là.
  3. Comment utiliser réellement l'algorithme?

MISE À JOUR

Ok, fait un port PHP du code montré dans le papier Gustavson, et comme l'a dit un autre codeur, il ne génère qu'une octave. Avez-vous un autre site / document / guide utile sur la façon de l'utiliser avec les concepts d'octaves multiples, d'amplitude, de fréquence, etc. pour contrôler la fonction de bruit? Sur le papier de Gustavson montre juste les résultats, pas l'implémentation réelle de l'algorithme, peut-être que je manque quelque chose?

MISE À JOUR 2
@NATHAN

J'ai fait quelque chose comme:

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

Et après avoir normalisé les valeurs à 0..1, j'obtiens une carte de hauteur plutôt terne telle que:

entrez la description de l'image ici

Comment amorcer la carte? Peut-être que je dois implémenter la version 3D avec la troisième valeur une hauteur aléatoire? Mais si c'est le cas, il faudrait que je prenne en considération les valeurs des voisins, que je terminerais par quelque chose comme un algorithme carré de diamant, exactement ce que je ne veux pas faire.

MISE À JOUR 3

Plus de travail Perlin. Je n'ai pas encore trouvé de moyen de guider le bruit vers mes résultats. Vérifiez ces octaves et le résultat final:

Octave I à IV

Octave1Octave2Octave3Octave4

Résumé

Octaves 1-4 résumées

Chaque octave est à peu près la même. Vérifiez le 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);

Les résultats sont normalisés. Qu'est-ce que vous utiliseriez pour influencer fortement le développement du bruit? Je vois des exemples où le changement d'amplitude donne des surfaces douces ou rugueuses, mais même si je donne une amplitude énorme, je vois peu de différence.

Gabriel A. Zorrilla
la source
Additionnez simplement plusieurs instances, augmentant la fréquence et diminuant l'amplitude à chaque fois, comme: perlin (x) + 0,5 * perlin (2 * x) + 0,25 * perlin (4 * x) + ... (pour autant d'octaves que tu veux). Vous pouvez également essayer de modifier les facteurs pour obtenir des looks différents; ils n'ont pas besoin d'être des pouvoirs de 2.
Nathan Reed
1
Après la mise à jour, il semble que vous n'échelonniez pas Y correctement - je suis trop fatigué pour faire du PHP (car je ne connais pas PHP); mais j'ai rencontré un problème similaire dans ma langue maternelle lors de la première mise en œuvre de Perlin. Tuez également les octaves et déboguez simplement un niveau de perlin.
Jonathan Dickinson,
Quelqu'un pour ma mise à jour III?
Gabriel A. Zorrilla

Réponses:

28

Ce que vous avez implémenté n'est pas du bruit Perlin. Je ne sais pas pourquoi Hugo Elias le dit, mais il est confus. Voici l'implémentation de référence de Ken Perlin. Il n'appelle en fait aucun générateur de nombres aléatoires externe, mais utilise une fonction de hachage intégrée pour produire les vecteurs de gradient pseudo-aléatoires.

Notez également que le bruit Perlin se compose d'une seule octave. Résumer plusieurs octaves (instances mises à l'échelle de la fonction de bruit), comme le suggère Hugo Elias, est une technique utile, mais ne fait pas partie du bruit de Perlin. Ce que vous obtenez en faisant cela est appelé bruit fractal, parfois «bruit brownien fractal» (en raison de la similitude supposée avec le mouvement brownien).

Si vous voulez comprendre géométriquement ce que fait l'algorithme, essayez cet article . Il s'agit d'un type de bruit différent appelé "bruit simplex", mais comprend également une explication du bruit Perlin classique. Soit dit en passant, le bruit simplex a également été inventé par Perlin et est censé être une amélioration par rapport à son bruit classique, vous pouvez donc essayer de l'implémenter aussi si vous êtes intéressé à jouer avec les fonctions de bruit.

Nathan Reed
la source
2
+1 pour le papier de Gustavson. Il explique le bruit perlin et simplex de la manière la plus claire que j'ai vue jusqu'à présent. De toute évidence des règles de bruit simplex!
FxIII
J'ai également trouvé ce papier il y a quelque temps, mais celui d'Hugo avait l'air plus simple. Je vais le lire et l'essayer! Merci!
Gabriel A. Zorrilla
2
soyez prudent lorsque vous téléchargez du bruit simplex, il pourrait avoir un virus;)
bobobobo
Je sais que c'est un vieux sujet, mais dire que l'implémentation de référence n'utilise pas un nombre aléatoire est incorrect. Lorsque la bibliothèque est initialisée (ou la première fois qu'une fonction de bruit est appelée), 256 gradients aléatoires sont générés. Le hachage auquel vous faites référence consiste simplement à contraindre l'ensemble infini d'entiers dans la plage [0, 255] qui est mise en cache. Essentiellement, ce n'est qu'une optimisation de table de recherche, et l'algorithme fonctionne aussi bien si, par exemple, vous amorcez un PRNG avec une coordonnée de grille et l'utilisez pour générer le gradient, c'est juste (beaucoup) plus lent de cette façon.
bcrist
@bcrist Je pense que vous faites référence à une ancienne version du bruit Perlin. Le "bruit amélioré" de Perlin, auquel j'ai lié , utilise un ensemble fixe de 12 vecteurs de gradient, et non 256 aléatoires. Il utilise une table de permutation comme fonction de hachage pour mapper les coordonnées de la grille à l'un de ces 12 vecteurs de gradient.
Nathan Reed
11

C'est une idée fausse commune. Ce que Hugo Elias appelle le bruit «Perlin» est en fait du bruit fractal ou rose. Pour mieux comprendre ce qu'est le bruit Perlin, vous pouvez lire l'article de Perlin lié dans la réponse de Nathan Reed, ou libnoise docs (il y a la même erreur là-bas: Perlin noise est ce qu'ils appellent Gradient noise), ou CoherentNoise docs .

Maintenant, pour répondre à votre question: vous n'avez pas obtenu le résultat attendu car la fréquence du bruit est trop élevée. Vos fréquences commencent par 1 et augmentent, ce qui signifie que chaque pixel de la carte résultante a une valeur aléatoire. Pour voir une structure plus fine de la carte, vous devez "zoomer" sur le bruit. Je ne parle pas vraiment PHP, mais je suppose que le code devrait ressembler à ceci:

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

Autrement dit, vous "étirez" une période de bruit sur l'ensemble de votre carte. Bien sûr, vous pouvez utiliser d'autres coefficients - essayez simplement différents, voyez ce qui se passe.

Ça ne fait rien
la source
Merci pour les documents sonores cohérents! Je vois que vous l'avez écrit :) Quelle est l'erreur dans les documents libnoise? Le bruit de Perlin n'est-il pas une sorte de bruit de gradient?
legends2k