-
-
Save nowl/828013 to your computer and use it in GitHub Desktop.
#include <stdio.h> | |
static int SEED = 0; | |
static int hash[] = {208,34,231,213,32,248,233,56,161,78,24,140,71,48,140,254,245,255,247,247,40, | |
185,248,251,245,28,124,204,204,76,36,1,107,28,234,163,202,224,245,128,167,204, | |
9,92,217,54,239,174,173,102,193,189,190,121,100,108,167,44,43,77,180,204,8,81, | |
70,223,11,38,24,254,210,210,177,32,81,195,243,125,8,169,112,32,97,53,195,13, | |
203,9,47,104,125,117,114,124,165,203,181,235,193,206,70,180,174,0,167,181,41, | |
164,30,116,127,198,245,146,87,224,149,206,57,4,192,210,65,210,129,240,178,105, | |
228,108,245,148,140,40,35,195,38,58,65,207,215,253,65,85,208,76,62,3,237,55,89, | |
232,50,217,64,244,157,199,121,252,90,17,212,203,149,152,140,187,234,177,73,174, | |
193,100,192,143,97,53,145,135,19,103,13,90,135,151,199,91,239,247,33,39,145, | |
101,120,99,3,186,86,99,41,237,203,111,79,220,135,158,42,30,154,120,67,87,167, | |
135,176,183,191,253,115,184,21,233,58,129,233,142,39,128,211,118,137,139,255, | |
114,20,218,113,154,27,127,246,250,1,8,198,250,209,92,222,173,21,88,102,219}; | |
int noise2(int x, int y) | |
{ | |
int tmp = hash[(y + SEED) % 256]; | |
return hash[(tmp + x) % 256]; | |
} | |
float lin_inter(float x, float y, float s) | |
{ | |
return x + s * (y-x); | |
} | |
float smooth_inter(float x, float y, float s) | |
{ | |
return lin_inter(x, y, s * s * (3-2*s)); | |
} | |
float noise2d(float x, float y) | |
{ | |
int x_int = x; | |
int y_int = y; | |
float x_frac = x - x_int; | |
float y_frac = y - y_int; | |
int s = noise2(x_int, y_int); | |
int t = noise2(x_int+1, y_int); | |
int u = noise2(x_int, y_int+1); | |
int v = noise2(x_int+1, y_int+1); | |
float low = smooth_inter(s, t, x_frac); | |
float high = smooth_inter(u, v, x_frac); | |
return smooth_inter(low, high, y_frac); | |
} | |
float perlin2d(float x, float y, float freq, int depth) | |
{ | |
float xa = x*freq; | |
float ya = y*freq; | |
float amp = 1.0; | |
float fin = 0; | |
float div = 0.0; | |
int i; | |
for(i=0; i<depth; i++) | |
{ | |
div += 256 * amp; | |
fin += noise2d(xa, ya) * amp; | |
amp /= 2; | |
xa *= 2; | |
ya *= 2; | |
} | |
return fin/div; | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
int x, y; | |
for(y=0; y<4000; y++) | |
for(x=0; x<4000; x++) | |
perlin2d(x, y, 0.1, 4); | |
return 0; | |
} |
You can use that with CSFML, its cool thanks ! if some one ever use for procedural Generation MP me 👍
Very nice, thanks for sharing this!
I noticed that your implementation only works with non-negative x/y coordinates, which is a somewhat unnecessary restriction, especially considering how useful noise functions are when it comes to generating infinite maps. Here's a possible fix.
Perlin.h:
#ifndef PERLIN_H
#define PERLIN_H
extern double Perlin_Get2d(double x, double y, double freq, int depth);
#endif // PERLIN_H
Perlin.c:
#include "Perlin.h"
#include <math.h>
static const int SEED = 1985;
static const unsigned char HASH[] = {
208,34,231,213,32,248,233,56,161,78,24,140,71,48,140,254,245,255,247,247,40,
185,248,251,245,28,124,204,204,76,36,1,107,28,234,163,202,224,245,128,167,204,
9,92,217,54,239,174,173,102,193,189,190,121,100,108,167,44,43,77,180,204,8,81,
70,223,11,38,24,254,210,210,177,32,81,195,243,125,8,169,112,32,97,53,195,13,
203,9,47,104,125,117,114,124,165,203,181,235,193,206,70,180,174,0,167,181,41,
164,30,116,127,198,245,146,87,224,149,206,57,4,192,210,65,210,129,240,178,105,
228,108,245,148,140,40,35,195,38,58,65,207,215,253,65,85,208,76,62,3,237,55,89,
232,50,217,64,244,157,199,121,252,90,17,212,203,149,152,140,187,234,177,73,174,
193,100,192,143,97,53,145,135,19,103,13,90,135,151,199,91,239,247,33,39,145,
101,120,99,3,186,86,99,41,237,203,111,79,220,135,158,42,30,154,120,67,87,167,
135,176,183,191,253,115,184,21,233,58,129,233,142,39,128,211,118,137,139,255,
114,20,218,113,154,27,127,246,250,1,8,198,250,209,92,222,173,21,88,102,219
};
static int noise2(int x, int y)
{
int yindex = (y + SEED) % 256;
if (yindex < 0)
yindex += 256;
int xindex = (HASH[yindex] + x) % 256;
if (xindex < 0)
xindex += 256;
const int result = HASH[xindex];
return result;
}
static double lin_inter(double x, double y, double s)
{
return x + s * (y-x);
}
static double smooth_inter(double x, double y, double s)
{
return lin_inter( x, y, s * s * (3-2*s) );
}
static double noise2d(double x, double y)
{
const int x_int = floor( x );
const int y_int = floor( y );
const double x_frac = x - x_int;
const double y_frac = y - y_int;
const int s = noise2( x_int, y_int );
const int t = noise2( x_int+1, y_int );
const int u = noise2( x_int, y_int+1 );
const int v = noise2( x_int+1, y_int+1 );
const double low = smooth_inter( s, t, x_frac );
const double high = smooth_inter( u, v, x_frac );
const double result = smooth_inter( low, high, y_frac );
return result;
}
double Perlin_Get2d(double x, double y, double freq, int depth)
{
double xa = x*freq;
double ya = y*freq;
double amp = 1.0;
double fin = 0;
double div = 0.0;
for (int i=0; i<depth; i++)
{
div += 256 * amp;
fin += noise2d( xa, ya ) * amp;
amp /= 2;
xa *= 2;
ya *= 2;
}
return fin/div;
}
@deeemmell I hope you don't mind, I incorporated your fix into my Lua binding.
@max1220 Quite to the contrary -- glad to hear that!
Very Helpful Thanks Very Much @nowl
Is it all good if I incorporate your fix @deeemmell to my project ?
Thanks Very Much
EPICPEARS
Is it all good if I incorporate your fix @deeemmell to my project ?
Absolutely, please feel free to do so. Cheers!
What's the license for this?
What's the license for this?
@sherief
"Hippity hoppity your code is now my property"
this is value noise, not perlin noise - it's way blockier
Hippity hoppity your code is now my property!
Thanks a ton, @nowl and @deeemmell!
This is the only sane code for Perlin Noise I could find on the interwebs.
I used it here.
It's not the Perlin noise, it's the value noise. Ken Perlin used random vectors instead of random numbers
HASH is very flawed. It only has 163 unique numbers, many repeated more than twice. 245 appears 5 times? This should just be a random permutation of all values from 0 to 255. This drastically reduces the effective randomness of your hashing.
Also, as pointed out above, this isn't Perlin noise, which should be generating a random normal vector at each corner, computing a dot product, and then interpolating that. It does use the smooth-step interpolation and the harmonic/fractal layering that normally comes with Perlin noise, but misses the core property that makes Perlin noise different than other types of noise.
One more thing: consider having SEED affect both X and Y in some way. The current implementation just adds it to Y, which means that all seeds are the same, just vertically displaced from each other. I think more ideally your random seed would be used to re-shuffle HASH instead.
I hope you minds, but I've created a small Lua C Module from this code! https://github.com/max1220/lua-perlin