From a2bc1eabec827e47c669159e635326fa34c50e0f Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Fri, 3 Mar 2017 10:37:20 -0800 Subject: [PATCH] perlin noise function pull request by Jack Mott but deleted before I could pull it --- stb_perlin.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 12 deletions(-) diff --git a/stb_perlin.h b/stb_perlin.h index fa144b2..5d76222 100644 --- a/stb_perlin.h +++ b/stb_perlin.h @@ -1,4 +1,4 @@ -// stb_perlin.h - v0.2 - perlin noise +// stb_perlin.h - v0.3 - perlin noise // public domain single-file C implementation by Sean Barrett // // LICENSE @@ -9,8 +9,8 @@ // to create the implementation, // #define STB_PERLIN_IMPLEMENTATION // in *one* C/CPP file that includes this file. - - +// +// // Documentation: // // float stb_perlin_noise3( float x, @@ -31,22 +31,55 @@ // 0 to mean "don't care". (The noise always wraps every 256 due // details of the implementation, even if you ask for larger or no // wrapping.) +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// 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_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_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain,int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// #ifdef __cplusplus -extern "C" float stb_perlin_noise3(float x, float y, float z, int x_wrap=0, int y_wrap=0, int z_wrap=0); -#else +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); +#ifdef __cplusplus +} #endif #ifdef STB_PERLIN_IMPLEMENTATION -#include // floor() - // 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 int 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, 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, @@ -89,6 +122,12 @@ static float stb__perlin_lerp(float a, float b, float t) return a + (b-a) * t; } +static int stb__perlin_fastfloor(float a) +{ + 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) { @@ -110,7 +149,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z) // 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/16ths and 6/16ths, and the same 4 cases get the extra weight. + // 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, @@ -122,6 +161,7 @@ static float stb__perlin_grad(int hash, float x, float y, float z) }; // 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; } @@ -136,9 +176,9 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z unsigned int x_mask = (x_wrap-1) & 255; unsigned int y_mask = (y_wrap-1) & 255; unsigned int z_mask = (z_wrap-1) & 255; - int px = (int) floor(x); - int py = (int) floor(y); - int pz = (int) floor(z); + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); int x0 = px & x_mask, x1 = (px+1) & x_mask; int y0 = py & y_mask, y1 = (py+1) & y_mask; int z0 = pz & z_mask, z1 = (pz+1) & z_mask; @@ -177,6 +217,60 @@ 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) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + 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; + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + 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) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + 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; + frequency *= lacunarity; + amplitude *= gain; + } + 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) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + 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; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + #endif // STB_PERLIN_IMPLEMENTATION /*