Auteur Sujet: Seamless Tiling Perlin Noise  (Lu 842 fois)

0 Membres et 1 Invité sur ce sujet

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Seamless Tiling Perlin Noise
« le: 24 Octobre 2011 à 17:21:21 »
Yo !

Alors vous allez sans doute trouver ça très con vu que vous l'avez p'têt déjà fait mais bon, j'avais besoin de faire tiler du Perlin noise... Bah ouais, curieusement j'en avais jamais eu besoin avant.
Là je fais un mini générateur de noise pour créer des textures intéressantes pour mes nuages du coup il faut que ça tile.

J'ai cherché un peu partout sur ggl mais sans trouver de trucs vraiment satisfaisants. La plupart des types conseillent de faire un tiling entier, ou bien faire tiler 2 fois plus que la taille dont on a besoin et faire une moyenne des 4 tiles de noise. D'autres préconisent encore de faire un sampling du style :
Ftileable(x, y) = (
F(x, y) * (w - x) * (h - y) +
F(x - w, y) * (x) * (h - y) +
F(x - w, y - h) * (x) * (y) +
F(x, y - h) * (w - x) * (y)
) / (w * h)
(trouvé sur http://www.gamedev.net/topic/487457-more-seamless-tiling-perlin-noise/)

M'en fait bon, ça convient pas trop. C'est assez moche et on voit bien le mirroring.
Du coup, comme ma fonction de noise sample un noise 4D (histoire d'être bien générique) je me suis un peu creusé la tête pour voir comment je pouvais utiliser les 2 dimensions supplémentaires et je me suis dit que je pourrais sampler le long de 2 cercles, chaque cercle se trouvant dans 2 des 4 dimensions disponibles... Hébin ça marche super bien !
Donc je vous livre le p'tit algo ci-dessous qui peut toujours servir :

Le code de fbm déjà :
Random RNG = new Random( 1 );

Vector2 Position;
float Frequency = InitialTiling;   // Our initial, non-integer, tiling frequency
float Amplitude = 1.0f;

for ( int Octave=0; Octave < integerTrackbarControlOctavesCount.Value; Octave++ )
{
// These offsets are here to break the "origin replication" and offset octaves from one another
int XOffset = RNG.Next( (int) m_NoiseGen.NoiseSize );
int YOffset = RNG.Next( (int) m_NoiseGen.NoiseSize );

for ( int Y=0; Y < TextureSize; Y++ )
{
Position.Y = (float) (Y + YOffset) / TextureSize;   // Generates a coordinate in [random,random+1]
for ( int X=0; X < TextureSize; X++ )
{
Position.X = (float) (X + XOffset) / TextureSize;   // Generates a coordinate in [random,random+1]
Noise[X,Y] += Amplitude * GetTilingNoise( Position, Frequency );
}
}
Frequency *= FrequencyFactor;  // Also known as lacunarity
Amplitude *= AmplitudeFactor;  // Also known as persistence
}

Et le code de tiling noise :
protected static Vector4 NoisePos;
protected float GetTilingNoise( Vector2 _UV, float _TileLength )
{
// Generate points on 2 circles
double AngleX = 2.0 * Math.PI * _UV.x;
double AngleY = 2.0 * Math.PI * _UV.y;
NoisePos.x = _TileLength * (float) Math.Cos( AngleX );
NoisePos.y = _TileLength * (float) Math.Sin( AngleX );
NoisePos.z = _TileLength * (float) Math.Cos( AngleY );
NoisePos.w = _TileLength * (float) Math.Sin( AngleY );

return m_NoiseGen.GetNoise( NoisePos );
}

Alors bien entendu, c'est + lent mais pour du pre-process c'est nickel !
C'est également faisable avec un bête noise 3D en samplant sur un tore au lieu de 2 cercles.

Voilà, j'ai p'têt ré-inventé la roue mais bon, ça évitera de chercher vainement pendant des plombes et de perdre son temps sur d'innombrables tutorials de photoshop tous moisis... ;D
.  Pom  .

Hors ligne @lx

    • Pouet.net
    • Voir le profil
    • Code4k
  • Ancienneté: 1989
  • Groupe: FRequency
  • Rôle: code (+musique), web
  • Ville: Tokyo
Re : Seamless Tiling Perlin Noise
« Réponse #1 le: 25 Octobre 2011 à 02:14:54 »
Wow, excellente idée!  ;)

Hors ligne u2Popsy

    • Voir le profil
    • u2 Blog
  • Ancienneté: 1996
  • Groupe: PoPsY TeAm
  • Rôle: coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #2 le: 25 Octobre 2011 à 09:40:16 »
Si tu as besoin de faire tiler en 2D uniquement tu n'a rien a faire normalement... pourquoi ne pas simplement stocker un random dans une texture 2D correspondant au tile désiré qui te servira de base pour échantillonner tes octaves ?

Si par contre tu veux animer ton noise 2D de façon convaincante et que tu veux que cela boucle dans le temps alors voila ce qu'il te faut :
http://www.noisemachine.com/talk1/
et plus particulièrement ce slide :
http://www.noisemachine.com/talk1/24b.html
ou la composante Z = le temps compris en [0..1] et qui fera tiler ton noise x,y comme il faut dans le temps.

Pour ton résultat a base d'angle a mon avis cela doit introduire une sorte de "répétition" ou de pattern visuel mais bon reste à vérifier.

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #3 le: 25 Octobre 2011 à 11:06:39 »
Si par contre tu veux animer ton noise 2D de façon convaincante et que tu veux que cela boucle dans le temps alors voila ce qu'il te faut :
http://www.noisemachine.com/talk1/
et plus particulièrement ce slide :
http://www.noisemachine.com/talk1/24b.html
ou la composante Z = le temps compris en [0..1] et qui fera tiler ton noise x,y comme il faut dans le temps.

Oui je me servais déjà de ça pour animer, là ça marche encore pas trop mal.
Mais ce code, c'est celui que j'ai posté au dessus :
Ftileable(x, y) = (
F(x, y) * (w - x) * (h - y) +
F(x - w, y) * (x) * (h - y) +
F(x - w, y - h) * (x) * (y) +
F(x, y - h) * (w - x) * (y)
) / (w * h)

Et franchement, tu vois le mirroring... 'fin moi j'aime pas.

Si tu as besoin de faire tiler en 2D uniquement tu n'a rien a faire normalement... pourquoi ne pas simplement stocker un random dans une texture 2D correspondant au tile désiré qui te servira de base pour échantillonner tes octaves ?

Comment ça rien à faire ?? Bah le Perlin noise boucle pas naturellement si tu prends pas des fréquences multiples de la taille de ta table de permutation. 'fin moi j'y arrive pas en tout cas...

Pour ton résultat a base d'angle a mon avis cela doit introduire une sorte de "répétition" ou de pattern visuel mais bon reste à vérifier.

Non non, tu n'as pas de pattern visuel quand tu samples un noise 3D pour displacer des vertex sur une sphère non ? Bah là c'est pareil, sauf que c'est sur un tore...
.  Pom  .

Hors ligne u2Popsy

    • Voir le profil
    • u2 Blog
  • Ancienneté: 1996
  • Groupe: PoPsY TeAm
  • Rôle: coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #4 le: 25 Octobre 2011 à 11:16:38 »
Citer
Comment ça rien à faire ?? Bah le Perlin noise boucle pas naturellement si tu prends pas des fréquences multiples de la taille de ta table de permutation. 'fin moi j'y arrive pas en tout cas...

Pourquoi ne pas prendre des multiples de la table pour tes octaves ?

Citer
Non non, tu n'as pas de pattern visuel quand tu samples un noise 3D pour displacer des vertex sur une sphère non ? Bah là c'est pareil, sauf que c'est sur un tore...

Ok je visualise le truc maintenant c'est une bonne idée en effet ( un peu comme le principe de déformation dans le raymarching en fait ) et puis comme tu as le résultat sous les yeux et que tu semble satisfait ca doit le faire.. ;)
« Modifié: 25 Octobre 2011 à 11:28:31 par u2Popsy »

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #5 le: 25 Octobre 2011 à 14:30:46 »
Pourquoi ne pas prendre des multiples de la table pour tes octaves ?

Hé bien c'est pas pratique du tout si je veux un tiling très faible... Généralement, j'initialise ma table de permutation avec genre 2048 valeurs pour avoir une large marge de manoeuvre dans le noise.
Mais si je veux par exemple générer une texture qui boucle sur 1/100ème de cette table, bah je peux pas... Faut forcément des multiples entiers >= 1. Et si j'initialise avec une toute petite table, genre 8 valeurs permutées bah je trouve que ça offre pas assez de variations.
'fin p'têt que je configure mal mon noise, chais pas...

Ok je visualise le truc maintenant c'est une bonne idée en effet ( un peu comme le principe de déformation dans le raymarching en fait ) et puis comme tu as le résultat sous les yeux et que tu semble satisfait ca doit le faire.. ;)


Oui oui ça marche super bien ! La preuve en image :


On voit bien le tiling mais y a pas d'artefacts ('fni j'en vois pas). Et là ça tile sur 0.5528 unités de noise... Soit 1/1132ème de la table.
.  Pom  .

Hors ligne u2Popsy

    • Voir le profil
    • u2 Blog
  • Ancienneté: 1996
  • Groupe: PoPsY TeAm
  • Rôle: coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #6 le: 25 Octobre 2011 à 14:40:52 »
Ouaip visuellement c'est nickel
Sinon tu fais ca pour ton projet de plugin de nuage ? Tu as bientot terminé ?



Hors ligne flure

    • Pouet.net
    • Voir le profil
    • Geek n'Roll
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #7 le: 25 Octobre 2011 à 19:30:05 »
Haaaaan ça m'intéresse ! J'avais posé exactement la même question ici il y a quelques [mois | années] (rayer la mention inutile) ;)

Hors ligne @lx

    • Pouet.net
    • Voir le profil
    • Code4k
  • Ancienneté: 1989
  • Groupe: FRequency
  • Rôle: code (+musique), web
  • Ville: Tokyo
Re : Seamless Tiling Perlin Noise
« Réponse #8 le: 26 Octobre 2011 à 00:46:41 »
Hé bien c'est pas pratique du tout si je veux un tiling très faible... Généralement, j'initialise ma table de permutation avec genre 2048 valeurs pour avoir une large marge de manoeuvre dans le noise.
Mais si je veux par exemple générer une texture qui boucle sur 1/100ème de cette table, bah je peux pas... Faut forcément des multiples entiers >= 1. Et si j'initialise avec une toute petite table, genre 8 valeurs permutées bah je trouve que ça offre pas assez de variations.
'fin p'têt que je configure mal mon noise, chais pas...

Effectivement, ça ne marche pas et c'est pour cela que l'on est obligé d'utiliser une fonction de tiling par dessus.
Sinon oui Flure, on en avait parle sur "bruit de perlin-pinpin",  Patapom a l'epoque te proposait aussi un truc similaire a ce que suggere ici u2Popsy :P alors qu'il faut effectivement utiliser des fonctions de tiling par dessus le perlin pour pouvoir tiler comme tu veux et pas avoir des restrictions sur des multiples d'octaves...

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #9 le: 27 Novembre 2011 à 15:03:14 »
Petit update par rapport à ce que j'avais dit :

J'avais émis l'idée qu'en prenant les coordonnées de noise sur la surface d'un tore, on obtiendrait un noise qui tile correct : c'est faux !
Disons que ça marche, le noise tile bien, mais on a des "bandes" qui apparaissent, des zones qui semblent plus étendues et d'autres plus compactes.

Voilà le résultat :


Et ça vient simplement de la topologie du tore, comme montré sur l'image ci-dessous où l'on voit un tore vu du dessus :


C'est @lx qui m'a fait part de ce problème et il n'y a pas vraiment moyen de s'en sortir : il faudrait une surface qui boucle et dont le rayon de courbure est identique partout, j'en connais qu'une : la sphère (ou les fameux 2 cercles en 4D qui, eux, fonctionnent très bien). Or, on sait tous à quel point la sphère est chiante à mapper...
Avec une sphère, ça "tile" aussi mais c'est encore pire à cause des pôles :


Bref, je poste cette remarque ici pour pas que vous fassiez fausse route si jamais vous décidiez d'utiliser cette technique de tiling. Je ré-itère toutefois l'affirmation que sampler 2 cercles dans un noise 4D fonctionne très bien ! Si vous faites des texture shaders en DX9 pour précalculer des maps de noise qui tilent, la fonction "noise()" peut prendre un float4 et donc être utilisée pour cette technique.

Finalement, en jouant un peu j'ai réussi à obtenir une chouette illusion d'optique qui devrait me permettre d'hypnotiser un cochon d'inde :



Bisous !
« Modifié: 27 Novembre 2011 à 16:51:59 par Patapom »
.  Pom  .

Hors ligne u2Popsy

    • Voir le profil
    • u2 Blog
  • Ancienneté: 1996
  • Groupe: PoPsY TeAm
  • Rôle: coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #10 le: 27 Novembre 2011 à 18:54:14 »
Ben c'est bizarre tu avais posté une image ou cela tilait correctement...
Mais ce que tu poste maintenant correspond a ce que je pensais au départ, comment tu avais obtenu le 1er résultat ?

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #11 le: 27 Novembre 2011 à 19:48:43 »
Ben c'est ce que j'ai dit : les 2 cercles en 4D fonctionnent... C'est juste que tout le monde a pas du noise 4D à disposition et avec un simple noise 3D bah c'est pas possible de le faire boucler correctement sans déformations... :-\
.  Pom  .

Hors ligne @lx

    • Pouet.net
    • Voir le profil
    • Code4k
  • Ancienneté: 1989
  • Groupe: FRequency
  • Rôle: code (+musique), web
  • Ville: Tokyo
Re : Seamless Tiling Perlin Noise
« Réponse #12 le: 28 Novembre 2011 à 04:00:53 »
Comme je cherchais a faire un noise3d tileable, je suis tombé sur un autre article "Seamless noise", avec un gars qui avait eu la même idée d'utiliser un noise4d pour faire un tile sur du 2d! ;)

Donc résultat, pour faire un noise3d tileable, il faut avoir un noise de base en 6D, et comme j'utilise du Simplex sur GPU, ben ca a l'air coton pour faire une implem avec les bons coeffs...  :(

Hors ligne u2Popsy

    • Voir le profil
    • u2 Blog
  • Ancienneté: 1996
  • Groupe: PoPsY TeAm
  • Rôle: coder
  • Ville: Lyon
Re : Seamless Tiling Perlin Noise
« Réponse #13 le: 28 Novembre 2011 à 09:25:03 »
Citer
en c'est ce que j'ai dit : les 2 cercles en 4D fonctionnent...
Dans ton poste avec le rendu correct tu laissais entendre que c'était la version "tore" du noise voila pour le quiproquo.

Hors ligne Patapom

    • Voir le profil
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Re : Seamless Tiling Perlin Noise
« Réponse #14 le: 28 Novembre 2011 à 15:13:43 »
Dans ton poste avec le rendu correct tu laissais entendre que c'était la version "tore" du noise voila pour le quiproquo.
Oui, je viens de relire et effectivement on peut se méprendre...

Donc résultat, pour faire un noise3d tileable, il faut avoir un noise de base en 6D, et comme j'utilise du Simplex sur GPU, ben ca a l'air coton pour faire une implem avec les bons coeffs...  :(
Ah ouais, toi en + tu veux un noise tileable 3D ! Ouch...

Mais c'est dans quel cadre exactement ?? C'est pour un pixel shader ou c'est juste une routine de précalc ?
Parce que si c'est du précalc et que tu as déjà une routine de noise 3D à disposition, c'est assez facile d'avoir du 6D : tu continues à lerper comme un porc...
float4 N0 = float4( noise3D( p0 ), noise3D( p0 + OFFSET0 ), noise3D( p0 + OFFSET1 ), noise3D( p0 + OFFSET2 ) );
float4 N1 = float4( noise3D( p0 + OFFSET3 ), noise3D( p0 + OFFSET4 ), noise3D( p0 + OFFSET5 ), noise3D( p0 + OFFSET6 ) );
float4 N = lerp( N0, N1, p1.z );
N.xy = lerp( N.xy, N.zw, p1.y );
return lerp( N.x, N.y, p1.x );

Avec p0 tes 3 premières coords et p1 tes 3 suivantes...
Mais effectivement, si c'est dans le cadre d'une routine à appeler en realtime, j'peux comprendre que sampler 8 fois le noise 3D par appel, ça puisse poser problème ! ;D
.  Pom  .

 

Dans la Réponse Rapide, vous pouvez utiliser du BBCode et des smileys comme sur un message normal, mais à partir d'une interface plus rapide d'accès.

Attention, il n'y a pas eu de réponse à ce sujet depuis au moins 30 jours.
À moins que vous ne soyez sûr de vouloir répondre, pensez éventuellement à créer un nouveau sujet.

Nom: E-mail:
Vérification:
Quel est la couleur du cheval rouge d'Henri IV ?: