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...
