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

0 Membres et 2 Invités sur ce sujet

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 #15 le: 29 Novembre 2011 à 04:47:29 »
Mais c'est dans quel cadre exactement ?? C'est pour un pixel shader ou c'est juste une routine de précalc ?
Oui, c'est pour du pur precalc pour l'instant, meme si je veux que ce precalc se fasse sur le GPU pour pas que ca mette une plombe pour generer ces textures...

Bon, pour ton idee, je suis pas sur de la plage de valeur pour p1: autant pour p0, je peux multiplier par un facteur de tile non entier, autant pour p1, je dois avoir des valeurs entre  0 et 1, pour le coup ca marche pas trop.

In infine, j'aimerais avoir un code comme ca:
    float Compute(float3 pos, float frequency) {
float3 p0 = float3(cos(PI2 * pos.x), sin(PI2 * pos.x), cos(PI2 * pos.y))/2 + .5;
float3 p1 = float3(sin(PI2 * pos.y), cos(PI2 * pos.z), sin(PI2 * pos.z))/2 + .5;
return snoise6D(frequency * p0, frequency * p1);
     }
Le problème est que je peux pas vraiment multiplier p1 par frequency s'il s'attend derrière a un [0,1]... ou alors, j'ai rien compris a ta suggestion!  ;D

Hors ligne nystep

    • Pouet.net
    • Voir le profil
    • lostgarden
  • Ancienneté: 1995
  • Rôle: code
  • Ville: Jyväskylä
Re : Seamless Tiling Perlin Noise
« Réponse #16 le: 29 Novembre 2011 à 08:29:57 »
Aie, mais, mm, comment dire, y-a-t-il une raison logique que je n'arrive pas à saisir pour laquelle tu fais un sin/cos des coordonées avant de les injecter dans la routine de noise? pourquoi pas juste un frac() qui rendrait l'entrée linéaire? selon la routine de noise celà peut influer sur le résultat.. ( ? ) :) j'essaie juste de comprendre le souci.
"L'être humain met 2 ans a apprendre le langage mais toute une vie pour apprendre à se taire."

Hors ligne nystep

    • Pouet.net
    • Voir le profil
    • lostgarden
  • Ancienneté: 1995
  • Rôle: code
  • Ville: Jyväskylä
Re : Seamless Tiling Perlin Noise
« Réponse #17 le: 29 Novembre 2011 à 08:35:29 »
J'avais fait ce générateur de texture pour 4k il y a un moment, ça génère un perlin à 9 octaves qui tile (la routine de noise 3d marche nickel) dans une texture de 512x512 et ça essaie de faire un cellular correct (artefacts..):

vec4 c(vec4 x)
{
x-=fract(x);x/=512.0;
return fract((x*1.172+0.5)*(x*5.911+0.1)*(x*7.352+0.9));
}

float b(vec3 p,float t)
{
vec3 q=floor(p+0.5),u=0.5*sin((p-q)*3.1416)+0.5,v=vec3(11,59,151);
vec3 qv=mod(q,t)*v,rv=mod(q+1,t)*v;
vec4 m=mix(c(vec4(qv.x+qv.y+qv.z,rv.x+qv.y+qv.z,qv.x+rv.y+qv.z,rv.x+rv.y+qv.z)),c(vec4(qv.x+qv.y+rv.z,rv.x+qv.y+rv.z,qv.x+rv.y+rv.z,rv.x+rv.y+rv.z)),u.z);
vec2 o=mix(m.xy,m.zw,u.y);
return mix(o.x,o.y,u.x);
}

void main()
{
float y=1,z;
vec2 x=vec2(0);
vec3 a=vec3(1),v=vec3(11,59,151);
for(int i=0;i<9;i++)
{
z=b(gl_FragCoord.xyz*y,512.0*y);
x+=vec2(z,sin((z-0.5)/0.5)+0.5)/(512.0*y);
y*=0.5;
}
for(int j=-1;j<2;j++)
for(int i=-1;i<2;i++)
{
vec2 p=mod(floor(gl_FragCoord.xy/32.0)+vec2(i,j),16.0);
vec2 q=vec2(dot(p.xyx,v),dot(p.yxy,v));
float d=length(gl_FragCoord.xy-(p+c(q.xyxy).xy)*32.0)/64.0;
if(d<a.x){a.x=d;}
else if(d<a.y){a.y=d;}
else if(d<a.z){a.z=d;}
}
gl_FragColor=vec4(x.x,x.y,a.x,a.z);
}

Bon le code est pas top et il est optimisable, mais c'était à l'époque ou je conaissais pas shader_minifier donc un peu d'indulgence siouplai. ;)
"L'être humain met 2 ans a apprendre le langage mais toute une vie pour apprendre à se taire."

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 #18 le: 29 Novembre 2011 à 08:54:25 »
Aie, mais, mm, comment dire, y-a-t-il une raison logique que je n'arrive pas à saisir pour laquelle tu fais un sin/cos des coordonées avant de les injecter dans la routine de noise? pourquoi pas juste un frac() qui rendrait l'entrée linéaire? selon la routine de noise celà peut influer sur le résultat.. ( ? ) :) j'essaie juste de comprendre le souci.
Tu as lu le 1er post de Patapom? Parceque c'est lui qui a introduit les cos&sin, j'y suis pour rien moaaa!  ;D
C'est justement pour pouvoir tiler sur des fractions de la table initiale... C'est a ma connaissance la seule méthode valable (apres l'interpolation classique en préambule du post de Patapom, tout au début).

Grosso modo, pour faire un noise2D tileable tu utilises un 4d en samplant avec 2 cercles comme l'a explique Patapom:   
return noise4D(tileFactor * float4(cos(PI2*pos.x), sin(PI2*pos.x), cos(PI2*pos.y), sin(PI2*pos.y)));

Pour faire un noise tileable en 3D, il faut passer par un noise6D, et se balader sur 3 cercles (je fake l'existence d'un float6 hein):
return noise6D(tileFactor * float6(cos(PI2*pos.x), sin(PI2*pos.x), cos(PI2*pos.y), sin(PI2*pos.y), cos(PI2*pos.z), sin(PI2*pos.z)));

En utilisant ces cercles, tu boucles naturellement sur les valeurs, sans que la texture finale ne souffre d'un effet de tiling, avec en plus la souplesse de pouvoir faire varier la frequence de tiling qui n'est plus obligatoirement multiple entier de la taille de permutation...

nb: J'ai rien compris a ton code.  ;D

Hors ligne nystep

    • Pouet.net
    • Voir le profil
    • lostgarden
  • Ancienneté: 1995
  • Rôle: code
  • Ville: Jyväskylä
Re : Seamless Tiling Perlin Noise
« Réponse #19 le: 29 Novembre 2011 à 12:49:55 »
Ah scuse en fait je suis juste un boulet qui a pas lu tout le thread avant de répondre  ;D

Pour les cercles ok, mais effectivement, en termes de fréquence je pense qu'il y aura des soucis ( quand on sample sur un cercle du noise interpolé, mm, et bien ça fait comme dans les screenshots non?  :-[ ). Quoique je ne sais pas.

J'avais vu une section sur la manière de projeter du noise (3.7) dans ce papier sur le Wavelet Noise:

(Effectivement c'est la manière -parfaite- de projeter du noise, en faisant l'intégrale dans les dimensions supplémentaires, c'est sur que ça sera nickel le résultat, à moins de trouver des approximations)

http://graphics.pixar.com/library/WaveletNoise/paper.pdf
"L'être humain met 2 ans a apprendre le langage mais toute une vie pour apprendre à se taire."

Hors ligne nystep

    • Pouet.net
    • Voir le profil
    • lostgarden
  • Ancienneté: 1995
  • Rôle: code
  • Ville: Jyväskylä
Re : Seamless Tiling Perlin Noise
« Réponse #20 le: 29 Novembre 2011 à 12:51:32 »
La manière la plus simple et la plus courante ça reste quand même de prendre une "tranche" de noise en mettant un z et un w constant dans la fonction.
"L'être humain met 2 ans a apprendre le langage mais toute une vie pour apprendre à se taire."

Hors ligne nystep

    • Pouet.net
    • Voir le profil
    • lostgarden
  • Ancienneté: 1995
  • Rôle: code
  • Ville: Jyväskylä
Re : Seamless Tiling Perlin Noise
« Réponse #21 le: 29 Novembre 2011 à 13:10:58 »
Bien en fait oui c'est exactement ça que le code au dessus fait, j'implémente la méthode:

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)

en 3d en rajoutant z, j'utilise deux vec4 (donc 8 valeurs) que je mix tout à la fin pour arriver à ça.

La technique c'est d'associer un entier à chaque "pixel" de noise (je met des guillemets car selon la fréquence du noise désiré la notion de "pixel" peut varier). Cela permet de projeter tout noise sur une fonction 1d déterministe (du pseudo noise). La fonction b implémente cela. Le truc c'est de calculer les indices des 8 pixels autour et d'appeler la fonction de noise 1d (qui fonctionne sur des vec4 dans mon cas.. ça calcule donc 4 valeurs aléatoires à la fois). Et ensuite on fait l'interpolation à la main des 8 pixels environnants. C'est ce qui est fait pour deux vec4 par u.z dans mon code, ensuite je n'ai plus que deux vec2 à interpoler par u.y et finalement deux floats par u.x.

Comme u est calculé de cette manière, vec3 q=floor(p+0.5),u=0.5*sin((p-q)*3.1416)+0.5

(floor(p+0.5) = round(p) si la fonction round est supportée dans ton langage de shading favori)

Cela fait un noise de classe infinie puisque le sinus est dérivable à l'infini (d'autres utilisent la fonction smoothstep ou un polynôme de degré 5). C'est aussi possible de stocker toutes les valeurs de noise dans une texture et d'utiliser le filtrage linéaire ou de rectifier en faisant des lookups de tous les texels à la main avec le filtrage qui te convient.

EDIT: je raconte des aneries encore, ce qui fait tiler le noise c'est ça:

vec3 qv=mod(q,t)*v,rv=mod(q+1,t)*v;

t étant la "taille" en pixels sur laquelle le noise devrait tiler. q est la coordonnée en 3d du "pixel", et ensuite les différentes composantes xyz de q sont combinées dans la ligne qui est super longue et illisible pour former le cube.
« Modifié: 29 Novembre 2011 à 13:21:15 par nystep »
"L'être humain met 2 ans a apprendre le langage mais toute une vie pour apprendre à se taire."

 

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 ?: