@ -1,4 +1,4 @@
// stb_perlin.h - v0.3 - perlin noise
// stb_perlin.h - v0.4 - perlin noise
// public domain single-file C implementation by Sean Barrett
//
// LICENSE
@ -18,7 +18,8 @@
// float z,
// int x_wrap=0,
// int y_wrap=0,
// int z_wrap=0)
// int z_wrap=0,
// unsigned char seed=0)
//
// This function computes a random value at the coordinate (x,y,z).
// Adjacent random values are continuous but the noise fluctuates
@ -32,6 +33,9 @@
// details of the implementation, even if you ask for larger or no
// wrapping.)
//
// Using a different "seed" will provide a unique variation
// of the noise output.
//
// Fractal Noise:
//
// Three common fractal noise functions are included, which produce
@ -41,15 +45,15 @@
//
// float stb_perlin_ridge_noise3(float x, float y, float z,
// float lacunarity, float gain, float offset, int octaves,
// int x_wrap, int y_wrap, int z_wrap);
// unsigned char seed=0)
//
// float stb_perlin_fbm_noise3(float x, float y, float z,
// float lacunarity, float gain, int octaves,
// int x_wrap, int y_wrap, int z_wrap );
// unsigned char seed=0 );
//
// float stb_perlin_turbulence_noise3(float x, float y, float z,
// float lacunarity, float gain,int octaves,
// int x_wrap, int y_wrap, int z_wrap);
// unsigned char seed=0)
//
// Typical values to start playing with:
// octaves = 6 -- number of "octaves" of noise3() to sum
@ -60,25 +64,27 @@
//
// Contributors:
// Jack Mott - additional noise functions
// Jordan Peck - seeded noise
//
# ifdef __cplusplus
extern " C " {
# endif
extern float stb_perlin_noise3 ( float x , float y , float z , int x_wrap , int y_wrap , int z_wrap ) ;
extern float stb_perlin_ridge_noise3 ( float x , float y , float z , float lacunarity , float gain , float offset , int octaves , int x_wrap , int y_wrap , int z_wrap ) ;
extern float stb_perlin_fbm_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , int x_wrap , int y_wrap , int z_wrap ) ;
extern float stb_perlin_turbulence_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , int x_wrap , int y_wrap , int z_wrap ) ;
extern float stb_perlin_noise3 ( float x , float y , float z , int x_wrap , int y_wrap , int z_wrap , unsigned char seed ) ;
extern float stb_perlin_ridge_noise3 ( float x , float y , float z , float lacunarity , float gain , float offset , int octaves , unsigned char seed ) ;
extern float stb_perlin_fbm_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , unsigned char seed ) ;
extern float stb_perlin_turbulence_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , unsigned char seed ) ;
# ifdef __cplusplus
}
# endif
# ifdef STB_PERLIN_IMPLEMENTATION
# include <math.h> // fabs()
// not same permutation table as Perlin's reference to avoid copyright issues;
// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
// @OPTIMIZE: should this be unsigned char instead of int for cache?
static unsigned char stb__perlin_randtab [ 512 ] =
{
23 , 125 , 161 , 52 , 103 , 117 , 70 , 37 , 247 , 101 , 203 , 169 , 124 , 126 , 44 , 123 ,
@ -115,6 +121,50 @@ static unsigned char stb__perlin_randtab[512] =
131 , 11 , 163 , 99 , 234 , 81 , 227 , 147 , 156 , 176 , 17 , 142 , 69 , 12 , 110 , 62 ,
27 , 255 , 0 , 194 , 59 , 116 , 242 , 252 , 19 , 21 , 187 , 53 , 207 , 129 , 64 , 135 ,
61 , 40 , 167 , 237 , 102 , 223 , 106 , 159 , 197 , 189 , 215 , 137 , 36 , 32 , 22 , 5 ,
} ;
// perlin's gradient has 12 cases so some get used 1/16th of the time
// and some 2/16ths. We reduce bias by changing those fractions
// to 21/256ths and 22/256ths
// same as array above but with value % 12
static unsigned char stb__perlin_randtab_mod12 [ 512 ] =
{
11 , 5 , 5 , 4 , 7 , 9 , 10 , 1 , 7 , 5 , 11 , 1 , 4 , 6 , 8 , 3 ,
8 , 10 , 1 , 9 , 3 , 6 , 1 , 10 , 0 , 4 , 4 , 1 , 9 , 6 , 11 , 0 ,
7 , 3 , 5 , 6 , 1 , 4 , 0 , 3 , 1 , 8 , 3 , 6 , 9 , 8 , 6 , 0 ,
8 , 2 , 0 , 1 , 1 , 6 , 5 , 11 , 9 , 1 , 3 , 6 , 2 , 6 , 11 , 9 ,
9 , 4 , 10 , 1 , 0 , 2 , 5 , 0 , 7 , 6 , 1 , 0 , 8 , 2 , 7 , 5 ,
10 , 8 , 4 , 9 , 2 , 11 , 9 , 3 , 3 , 10 , 10 , 10 , 11 , 8 , 6 , 4 ,
9 , 2 , 7 , 6 , 10 , 11 , 2 , 10 , 1 , 7 , 4 , 10 , 7 , 2 , 1 , 3 ,
5 , 7 , 10 , 8 , 1 , 8 , 7 , 8 , 8 , 3 , 4 , 8 , 4 , 4 , 7 , 2 ,
2 , 8 , 9 , 7 , 11 , 9 , 7 , 4 , 2 , 5 , 2 , 3 , 4 , 6 , 4 , 4 ,
10 , 11 , 0 , 11 , 8 , 0 , 6 , 10 , 0 , 2 , 3 , 7 , 3 , 8 , 4 , 6 ,
0 , 0 , 11 , 0 , 0 , 6 , 2 , 1 , 10 , 2 , 0 , 1 , 2 , 4 , 5 , 3 ,
7 , 1 , 5 , 1 , 1 , 6 , 5 , 0 , 7 , 4 , 5 , 8 , 9 , 10 , 9 , 3 ,
2 , 11 , 5 , 6 , 1 , 9 , 5 , 11 , 7 , 8 , 6 , 2 , 11 , 10 , 10 , 5 ,
11 , 11 , 7 , 3 , 6 , 9 , 11 , 3 , 0 , 8 , 5 , 10 , 9 , 0 , 2 , 2 ,
3 , 3 , 0 , 2 , 11 , 8 , 2 , 0 , 7 , 9 , 7 , 5 , 3 , 9 , 4 , 3 ,
1 , 4 , 11 , 9 , 6 , 7 , 10 , 3 , 5 , 9 , 11 , 5 , 0 , 8 , 10 , 5 ,
// and a second copy so we don't need an extra mask or static initializer
11 , 5 , 5 , 4 , 7 , 9 , 10 , 1 , 7 , 5 , 11 , 1 , 4 , 6 , 8 , 3 ,
8 , 10 , 1 , 9 , 3 , 6 , 1 , 10 , 0 , 4 , 4 , 1 , 9 , 6 , 11 , 0 ,
7 , 3 , 5 , 6 , 1 , 4 , 0 , 3 , 1 , 8 , 3 , 6 , 9 , 8 , 6 , 0 ,
8 , 2 , 0 , 1 , 1 , 6 , 5 , 11 , 9 , 1 , 3 , 6 , 2 , 6 , 11 , 9 ,
9 , 4 , 10 , 1 , 0 , 2 , 5 , 0 , 7 , 6 , 1 , 0 , 8 , 2 , 7 , 5 ,
10 , 8 , 4 , 9 , 2 , 11 , 9 , 3 , 3 , 10 , 10 , 10 , 11 , 8 , 6 , 4 ,
9 , 2 , 7 , 6 , 10 , 11 , 2 , 10 , 1 , 7 , 4 , 10 , 7 , 2 , 1 , 3 ,
5 , 7 , 10 , 8 , 1 , 8 , 7 , 8 , 8 , 3 , 4 , 8 , 4 , 4 , 7 , 2 ,
2 , 8 , 9 , 7 , 11 , 9 , 7 , 4 , 2 , 5 , 2 , 3 , 4 , 6 , 4 , 4 ,
10 , 11 , 0 , 11 , 8 , 0 , 6 , 10 , 0 , 2 , 3 , 7 , 3 , 8 , 4 , 6 ,
0 , 0 , 11 , 0 , 0 , 6 , 2 , 1 , 10 , 2 , 0 , 1 , 2 , 4 , 5 , 3 ,
7 , 1 , 5 , 1 , 1 , 6 , 5 , 0 , 7 , 4 , 5 , 8 , 9 , 10 , 9 , 3 ,
2 , 11 , 5 , 6 , 1 , 9 , 5 , 11 , 7 , 8 , 6 , 2 , 11 , 10 , 10 , 5 ,
11 , 11 , 7 , 3 , 6 , 9 , 11 , 3 , 0 , 8 , 5 , 10 , 9 , 0 , 2 , 2 ,
3 , 3 , 0 , 2 , 11 , 8 , 2 , 0 , 7 , 9 , 7 , 5 , 3 , 9 , 4 , 3 ,
1 , 4 , 11 , 9 , 6 , 7 , 10 , 3 , 5 , 9 , 11 , 5 , 0 , 8 , 10 , 5 ,
} ;
static float stb__perlin_lerp ( float a , float b , float t )
@ -124,12 +174,12 @@ static float stb__perlin_lerp(float a, float b, float t)
static int stb__perlin_fastfloor ( float a )
{
int ai = ( int ) a ;
return ( a < ai ) ? ai - 1 : ai ;
int ai = ( int ) a ;
return ( a < ai ) ? ai - 1 : ai ;
}
// different grad function from Perlin's, but easy to modify to match reference
static float stb__perlin_grad ( int hash , float x , float y , float z )
static float stb__perlin_grad ( int grad_idx , float x , float y , float z )
{
static float basis [ 12 ] [ 4 ] =
{
@ -147,26 +197,11 @@ static float stb__perlin_grad(int hash, float x, float y, float z)
{ 0 , - 1 , - 1 } ,
} ;
// perlin's gradient has 12 cases so some get used 1/16th of the time
// and some 2/16ths. We reduce bias by changing those fractions
// to 5/64ths and 6/64ths, and the same 4 cases get the extra weight.
static unsigned char indices [ 64 ] =
{
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,
0 , 9 , 1 , 11 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ,
} ;
// if you use reference permutation table, change 63 below to 15 to match reference
// (this is why the ordering of the table above is funky)
float * grad = basis [ indices [ hash & 63 ] ] ;
float * grad = basis [ grad_idx ] ;
return grad [ 0 ] * x + grad [ 1 ] * y + grad [ 2 ] * z ;
}
float stb_perlin_noise3 ( float x , float y , float z , int x_wrap , int y_wrap , int z_wrap )
float stb_perlin_noise3 ( float x , float y , float z , int x_wrap , int y_wrap , int z_wrap , unsigned char seed )
{
float u , v , w ;
float n000 , n001 , n010 , n011 , n100 , n101 , n110 , n111 ;
@ -190,22 +225,22 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z
y - = py ; v = stb__perlin_ease ( y ) ;
z - = pz ; w = stb__perlin_ease ( z ) ;
r0 = stb__perlin_randtab [ x0 ] ;
r1 = stb__perlin_randtab [ x1 ] ;
r0 = stb__perlin_randtab [ x0 + seed ] ;
r1 = stb__perlin_randtab [ x1 + seed ] ;
r00 = stb__perlin_randtab [ r0 + y0 ] ;
r01 = stb__perlin_randtab [ r0 + y1 ] ;
r10 = stb__perlin_randtab [ r1 + y0 ] ;
r11 = stb__perlin_randtab [ r1 + y1 ] ;
n000 = stb__perlin_grad ( stb__perlin_randtab [ r00 + z0 ] , x , y , z ) ;
n001 = stb__perlin_grad ( stb__perlin_randtab [ r00 + z1 ] , x , y , z - 1 ) ;
n010 = stb__perlin_grad ( stb__perlin_randtab [ r01 + z0 ] , x , y - 1 , z ) ;
n011 = stb__perlin_grad ( stb__perlin_randtab [ r01 + z1 ] , x , y - 1 , z - 1 ) ;
n100 = stb__perlin_grad ( stb__perlin_randtab [ r10 + z0 ] , x - 1 , y , z ) ;
n101 = stb__perlin_grad ( stb__perlin_randtab [ r10 + z1 ] , x - 1 , y , z - 1 ) ;
n110 = stb__perlin_grad ( stb__perlin_randtab [ r11 + z0 ] , x - 1 , y - 1 , z ) ;
n111 = stb__perlin_grad ( stb__perlin_randtab [ r11 + z1 ] , x - 1 , y - 1 , z - 1 ) ;
n000 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r00 + z0 ] , x , y , z ) ;
n001 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r00 + z1 ] , x , y , z - 1 ) ;
n010 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r01 + z0 ] , x , y - 1 , z ) ;
n011 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r01 + z1 ] , x , y - 1 , z - 1 ) ;
n100 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r10 + z0 ] , x - 1 , y , z ) ;
n101 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r10 + z1 ] , x - 1 , y , z - 1 ) ;
n110 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r11 + z0 ] , x - 1 , y - 1 , z ) ;
n111 = stb__perlin_grad ( stb__perlin_randtab_mod12 [ r11 + z1 ] , x - 1 , y - 1 , z - 1 ) ;
n00 = stb__perlin_lerp ( n000 , n001 , w ) ;
n01 = stb__perlin_lerp ( n010 , n011 , w ) ;
@ -218,7 +253,7 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z
return stb__perlin_lerp ( n0 , n1 , u ) ;
}
float stb_perlin_ridge_noise3 ( float x , float y , float z , float lacunarity , float gain , float offset , int octaves , int x_wrap , int y_wrap , int z_wrap )
float stb_perlin_ridge_noise3 ( float x , float y , float z , float lacunarity , float gain , float offset , int octaves , unsigned char seed )
{
int i ;
float frequency = 1.0f ;
@ -227,19 +262,19 @@ float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float
float sum = 0.0f ;
for ( i = 0 ; i < octaves ; i + + ) {
float r = ( float ) ( stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , x_wrap , y_wrap , z_wrap ) ) ;
r = r < 0 ? - r : r ; // fabs()
r = offset - r ;
float r = stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , 0 , 0 , 0 , seed ) ;
r = offset - fabs ( r ) ;
r = r * r ;
sum + = r * amplitude * prev ;
prev = r ;
frequency * = lacunarity ;
amplitude * = gain ;
seed + + ;
}
return sum ;
}
float stb_perlin_fbm_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , int x_wrap , int y_wrap , int z_wrap )
float stb_perlin_fbm_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , unsigned char seed )
{
int i ;
float frequency = 1.0f ;
@ -247,14 +282,15 @@ float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float ga
float sum = 0.0f ;
for ( i = 0 ; i < octaves ; i + + ) {
sum + = stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , x_wrap , y_wrap , z_wrap ) * amplitude ;
sum + = stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , 0 , 0 , 0 , seed ) * amplitude ;
frequency * = lacunarity ;
amplitude * = gain ;
seed + + ;
}
return sum ;
}
float stb_perlin_turbulence_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , int x_wrap , int y_wrap , int z_wrap )
float stb_perlin_turbulence_noise3 ( float x , float y , float z , float lacunarity , float gain , int octaves , unsigned char seed )
{
int i ;
float frequency = 1.0f ;
@ -262,11 +298,11 @@ float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity,
float sum = 0.0f ;
for ( i = 0 ; i < octaves ; i + + ) {
float r = stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , x_wrap , y_wrap , z_wrap ) * amplitude ;
r = r < 0 ? - r : r ; // fabs()
sum + = r ;
float r = stb_perlin_noise3 ( x * frequency , y * frequency , z * frequency , 0 , 0 , 0 , seed ) * amplitude ;
sum + = fabs ( r ) ;
frequency * = lacunarity ;
amplitude * = gain ;
seed + + ;
}
return sum ;
}