Added seed to perlin and fractals

Removed broken wrap from fractals
Used varied seeds for fractal octaves to remove artifact at origin
Removed indicies table in favour of mod12 permutation table, this reduces gradient bias and gives 3% performance increase
This commit is contained in:
Jordan 2018-01-29 22:50:45 +00:00
parent dfff6f5e7c
commit 67f588cbb5

View File

@ -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,
@ -117,6 +123,50 @@ static unsigned char stb__perlin_randtab[512] =
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)
{
return a + (b-a) * t;
@ -129,7 +179,7 @@ static int stb__perlin_fastfloor(float a)
}
// 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;
}