Here is a C++ class for generating Perlin Noise. It is strongly based on Ken Perlin's java reference (found here
http://mrl.nyu.edu/~perlin/noise/)
The source code can be downloaded from github at
https://github.com/WesOfX/perlin-noise.
Before I go into detail, here are some demos:
1 Octave, 8 Frequency
7 Octaves, 3 Frequency, 0.5 Peristence
3 Octaves. 32 Frequency, 0.5 Persistence (Thresholded to look like caves)
The API centers around a class named Generator. The declaration is as follows:
// A reference Perlin noise generator
class Generator{
// Permutation vector for pseudo-random numbers
std::vector<unsigned char> permutation;
public:
// Creates Perlin noise generator with reference permutation vector
Generator();
// Creates Perlin noise generator with a custom seed
Generator(unsigned int seed);
// Returns noise value between -1.0 and 1.0
double get(double x, double y, double z) const;
private:
// Functions for interpolating noise
static double lerp(double t, double a, double b);
static double fade(double t);
static double grad(int hash, double x, double y, double z);
};
To use this class, you simply construct an object and use the "get" function to generate noise. Here is an example:
// Create reference Perlin generator
Generator generator();
// Print noise at 55, 99, 0
std::cout << generator.get(55, 99, 0) << std::endl;
// Create new noise with new seed
generator = Generator(42);
// Print new noise at 55, 99, 0
std::cout << generator.get(55, 99, 0) << std::endl;
For convenience, I have created an additional class for generating fractal Perlin Noise in bulk. (Especially useful for procedural map generation in roguelikes) It has a constructor which accepts parameters for noise frequency, number of octaves, and persistence. The declaration is as follows:
// A 2D array of doubles containing noise with easy access methods
class Noise{
// 2D Array of doubles containing noise
std::vector<double> map;
// Dimensions of array
unsigned short width, height;
public:
// Creates empty noise map
Noise();
// Constructor that resizes map and populates it with noise
Noise(
unsigned short width, // Number of columns
unsigned short height, // Number of rows
double frequency, // Frequency of noise features
unsigned int octaves, // Number of octaves (halving frequency)
double persistence, // Compounding weight of octaves
unsigned int seed // Seed for Perlin noise engine
);
// Returns a double from the map at the desired location
// Values returned are between -1.0 and 1.0
// If the location does not exist, 0.0 is returned
double get(unsigned short x, unsigned short y) const;
// Resizes the noise map and populates it with noise
void generate(
unsigned short width, // Number of columns
unsigned short height, // Number of rows
double frequency, // Frequency of noise features
unsigned int octaves, // Number of octaves (halving frequency)
double persistence, // Compounding weight of octaves
unsigned int seed // Seed for Perlin noise
);
private:
// Sets the double at the provided location to the value provided
void set(unsigned short x, unsigned short y, double value);
// Resized the double array (Invalidates current data)
void resize(unsigned short width, unsigned short height);
};
To use this class, use the constructor to generate the noise and the "get" function to access the noise. Here is an example:
// Generate noise with generation constructor
Noise noise(
800, // width
600, // height
6.5, // frequency
3, // octaves
0.75, // persistence
42 // seed
);
// Print noise at 55, 99 using get function
std::cout << noise.get(55, 99) << std::endl;
// Generate new noise with generate function
noise.generate(
800, // width
600, // height
6.5, // frequency
3, // octaves
0.75, // persistence
9001 // new seed!
);
// Print new noise at 55, 99 using get function again
std::cout << noise.get(55, 99) << std::endl;
The demo images were generated with the following code using a ppm image library (
https://github.com/WesOfX/ppm-image):
int main(){
// Image size
static constexpr unsigned short width = 512, height = 512;
// Final image that will be saved
PPM::Image image(width, height);
// Noise that will be applied to image
Perlin::Noise noise(
width,
height,
4.0, // Frequency
6, // Octaves
0.5, // Persistence
0 // Seed
);
// Apply noise to image
for(unsigned short y = 0; y < height; y++){
for(unsigned short x = 0; x < width; x++){
// Convert noise value to 24 bit color value
auto value = (unsigned char)(((noise.get(x, y) + 1) / 2) * 255);
// Set pixel color to value
image.set(x, y, PPM::Color(value, value, value));
}
}
// Save noise image
image.write("Noise.ppm");
}
If you have any questions, feel free to post.
I you wish to read Ken Perlin's reference, it is located at
http://mrl.nyu.edu/~perlin/noise/The source is available on github at
https://github.com/WesOfX/perlin-noiseDemo images created with
https://github.com/WesOfX/ppm-imageThank you