mirror of
https://github.com/nothings/stb
synced 2024-12-15 12:22:55 +03:00
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:
parent
dfff6f5e7c
commit
67f588cbb5
132
stb_perlin.h
132
stb_perlin.h
@ -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
|
// public domain single-file C implementation by Sean Barrett
|
||||||
//
|
//
|
||||||
// LICENSE
|
// LICENSE
|
||||||
@ -18,7 +18,8 @@
|
|||||||
// float z,
|
// float z,
|
||||||
// int x_wrap=0,
|
// int x_wrap=0,
|
||||||
// int y_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).
|
// This function computes a random value at the coordinate (x,y,z).
|
||||||
// Adjacent random values are continuous but the noise fluctuates
|
// 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
|
// details of the implementation, even if you ask for larger or no
|
||||||
// wrapping.)
|
// wrapping.)
|
||||||
//
|
//
|
||||||
|
// Using a different "seed" will provide a unique variation
|
||||||
|
// of the noise output.
|
||||||
|
//
|
||||||
// Fractal Noise:
|
// Fractal Noise:
|
||||||
//
|
//
|
||||||
// Three common fractal noise functions are included, which produce
|
// 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 stb_perlin_ridge_noise3(float x, float y, float z,
|
||||||
// float lacunarity, float gain, float offset, int octaves,
|
// 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 stb_perlin_fbm_noise3(float x, float y, float z,
|
||||||
// float lacunarity, float gain, int octaves,
|
// 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 stb_perlin_turbulence_noise3(float x, float y, float z,
|
||||||
// float lacunarity, float gain,int octaves,
|
// 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:
|
// Typical values to start playing with:
|
||||||
// octaves = 6 -- number of "octaves" of noise3() to sum
|
// octaves = 6 -- number of "octaves" of noise3() to sum
|
||||||
@ -60,25 +64,27 @@
|
|||||||
//
|
//
|
||||||
// Contributors:
|
// Contributors:
|
||||||
// Jack Mott - additional noise functions
|
// Jack Mott - additional noise functions
|
||||||
|
// Jordan Peck - seeded noise
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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_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,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, unsigned char seed);
|
||||||
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_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,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, unsigned char seed);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STB_PERLIN_IMPLEMENTATION
|
#ifdef STB_PERLIN_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <math.h> // fabs()
|
||||||
|
|
||||||
// not same permutation table as Perlin's reference to avoid copyright issues;
|
// 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/
|
// 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] =
|
static unsigned char stb__perlin_randtab[512] =
|
||||||
{
|
{
|
||||||
23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123,
|
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,
|
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)
|
static float stb__perlin_lerp(float a, float b, float t)
|
||||||
{
|
{
|
||||||
return a + (b-a) * 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
|
// 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] =
|
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 },
|
{ 0,-1,-1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
// perlin's gradient has 12 cases so some get used 1/16th of the time
|
float *grad = basis[grad_idx];
|
||||||
// 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]];
|
|
||||||
return grad[0]*x + grad[1]*y + grad[2]*z;
|
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 u,v,w;
|
||||||
float n000,n001,n010,n011,n100,n101,n110,n111;
|
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);
|
y -= py; v = stb__perlin_ease(y);
|
||||||
z -= pz; w = stb__perlin_ease(z);
|
z -= pz; w = stb__perlin_ease(z);
|
||||||
|
|
||||||
r0 = stb__perlin_randtab[x0];
|
r0 = stb__perlin_randtab[x0+seed];
|
||||||
r1 = stb__perlin_randtab[x1];
|
r1 = stb__perlin_randtab[x1+seed];
|
||||||
|
|
||||||
r00 = stb__perlin_randtab[r0+y0];
|
r00 = stb__perlin_randtab[r0+y0];
|
||||||
r01 = stb__perlin_randtab[r0+y1];
|
r01 = stb__perlin_randtab[r0+y1];
|
||||||
r10 = stb__perlin_randtab[r1+y0];
|
r10 = stb__perlin_randtab[r1+y0];
|
||||||
r11 = stb__perlin_randtab[r1+y1];
|
r11 = stb__perlin_randtab[r1+y1];
|
||||||
|
|
||||||
n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z );
|
n000 = stb__perlin_grad(stb__perlin_randtab_mod12[r00+z0], x , y , z );
|
||||||
n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 );
|
n001 = stb__perlin_grad(stb__perlin_randtab_mod12[r00+z1], x , y , z-1 );
|
||||||
n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z );
|
n010 = stb__perlin_grad(stb__perlin_randtab_mod12[r01+z0], x , y-1, z );
|
||||||
n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 );
|
n011 = stb__perlin_grad(stb__perlin_randtab_mod12[r01+z1], x , y-1, z-1 );
|
||||||
n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z );
|
n100 = stb__perlin_grad(stb__perlin_randtab_mod12[r10+z0], x-1, y , z );
|
||||||
n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 );
|
n101 = stb__perlin_grad(stb__perlin_randtab_mod12[r10+z1], x-1, y , z-1 );
|
||||||
n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z );
|
n110 = stb__perlin_grad(stb__perlin_randtab_mod12[r11+z0], x-1, y-1, z );
|
||||||
n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 );
|
n111 = stb__perlin_grad(stb__perlin_randtab_mod12[r11+z1], x-1, y-1, z-1 );
|
||||||
|
|
||||||
n00 = stb__perlin_lerp(n000,n001,w);
|
n00 = stb__perlin_lerp(n000,n001,w);
|
||||||
n01 = stb__perlin_lerp(n010,n011,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);
|
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;
|
int i;
|
||||||
float frequency = 1.0f;
|
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;
|
float sum = 0.0f;
|
||||||
|
|
||||||
for (i = 0; i < octaves; i++) {
|
for (i = 0; i < octaves; i++) {
|
||||||
float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap));
|
float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,0,0,0,seed);
|
||||||
r = r<0 ? -r : r; // fabs()
|
r = offset - fabs(r);
|
||||||
r = offset - r;
|
|
||||||
r = r*r;
|
r = r*r;
|
||||||
sum += r*amplitude*prev;
|
sum += r*amplitude*prev;
|
||||||
prev = r;
|
prev = r;
|
||||||
frequency *= lacunarity;
|
frequency *= lacunarity;
|
||||||
amplitude *= gain;
|
amplitude *= gain;
|
||||||
|
seed++;
|
||||||
}
|
}
|
||||||
return sum;
|
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;
|
int i;
|
||||||
float frequency = 1.0f;
|
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;
|
float sum = 0.0f;
|
||||||
|
|
||||||
for (i = 0; i < octaves; i++) {
|
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;
|
frequency *= lacunarity;
|
||||||
amplitude *= gain;
|
amplitude *= gain;
|
||||||
|
seed++;
|
||||||
}
|
}
|
||||||
return sum;
|
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;
|
int i;
|
||||||
float frequency = 1.0f;
|
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;
|
float sum = 0.0f;
|
||||||
|
|
||||||
for (i = 0; i < octaves; i++) {
|
for (i = 0; i < octaves; i++) {
|
||||||
float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude;
|
float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,0,0,0,seed)*amplitude;
|
||||||
r = r<0 ? -r : r; // fabs()
|
sum += fabs(r);
|
||||||
sum += r;
|
|
||||||
frequency *= lacunarity;
|
frequency *= lacunarity;
|
||||||
amplitude *= gain;
|
amplitude *= gain;
|
||||||
|
seed++;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user