Skip to content

Instantly share code, notes, and snippets.

@biomood
Created May 21, 2012 19:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save biomood/2763999 to your computer and use it in GitHub Desktop.
Save biomood/2763999 to your computer and use it in GitHub Desktop.
perlin noise in C, uses lodepng library
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "lodepng.h"
#define WIDTH 400
#define HEIGHT 400
#define PI (3.141592653589793)
static void generatewhitenoise(float m[WIDTH][HEIGHT]);
static void generatesmoothnoise(float basenoise[WIDTH][HEIGHT], float smooth[WIDTH][HEIGHT], int octave);
static void generateperlinnoise(float basenoise[WIDTH][HEIGHT], float perlin[WIDTH][HEIGHT], int octavecount);
static float interpolate(float x0, float x1, float alpha);
static float cosineinterpolate(float x0, float x1, float alpha);
static void setmatrix(float m[WIDTH][HEIGHT], float val);
static void printmatrix(float m[WIDTH][HEIGHT], char title[]);
static void matrixtoimage(float m[WIDTH][HEIGHT], char filename[]);
void matrixtoimage(float m[WIDTH][HEIGHT], char filename[]) {
unsigned char* image = malloc(WIDTH*HEIGHT);
int j;
for (j=0; j<HEIGHT; j++) {
int i;
for (i=0; i<WIDTH; i++) {
image[(WIDTH * j) + i] = floor(m[i][j] == 1.0 ? 255 : m[i][j] * 256.0);
}
}
LodePNGColorType gray = LCT_GREY;
lodepng_encode_file(filename, image, WIDTH, HEIGHT, gray, 8);
}
void printmatrix(float m[WIDTH][HEIGHT], char title[]) {
printf("%s \n", title);
int i;
for (i=0; i<WIDTH; i++) {
int j;
for (j=0; j<HEIGHT; j++) {
printf("%f, ", m[i][j]);
}
printf("\n");
}
}
void setmatrix(float m[WIDTH][HEIGHT], float val) {
int i;
for (i=0; i<WIDTH; i++) {
int j;
for (j=0; j<HEIGHT; j++) {
m[i][j] = val;
}
}
}
float interpolate(float x0, float x1, float alpha) {
return x0 * (1-alpha)+alpha*x1;
}
float cosineinterpolate(float x0, float x1, float alpha) {
float alpha2 = (1 - cos(alpha * PI)) / 2;
return (x0 * (1 - alpha2) + x1 * alpha2);
}
void generatewhitenoise(float m[WIDTH][HEIGHT]) {
int i;
for (i=0; i<WIDTH; i++) {
int j;
for (j=0; j<HEIGHT; j++) {
m[i][j] = (float)rand()/(float)RAND_MAX;
}
}
}
void generatesmoothnoise(float basenoise[WIDTH][HEIGHT],float smooth[WIDTH][HEIGHT], int octave) {
setmatrix(smooth, 0.0f);
int sampleperiod = 1 << octave;
float samplefrequency = 1.0f/sampleperiod;
int i;
for (i=0; i<WIDTH; i++) {
int samplei0 = (i/sampleperiod)*sampleperiod;
int samplei1 = (samplei0+sampleperiod)%WIDTH;
float horizontalblend = (i-samplei0)*samplefrequency;
int j;
for (j=0; j<HEIGHT; j++) {
int samplej0 = (j/sampleperiod)*sampleperiod;
int samplej1 = (samplej0+sampleperiod)%HEIGHT;
float verticalblend = (j-samplej0)*samplefrequency;
float top = cosineinterpolate(basenoise[samplei0][samplej0], basenoise[samplei1][samplej0], horizontalblend);
float bottom = cosineinterpolate(basenoise[samplei0][samplej1], basenoise[samplei1][samplej1], horizontalblend);
smooth[i][j] = cosineinterpolate(top, bottom, verticalblend);
}
}
}
void generateperlinnoise(float basenoise[WIDTH][HEIGHT], float perlin[WIDTH][HEIGHT], int octavecount) {
float smooth[octavecount][WIDTH][HEIGHT];
float persistence = 0.7f;
int i;
for (i=0; i<octavecount; i++) {
generatesmoothnoise(basenoise, smooth[i], i);
}
setmatrix(perlin, 0.0f);
float amplitude = 1.0f;
float totalamplitude = 1.0f;
int octave;
for (octave = octavecount - 1; octave >= 0; octave--) {
amplitude *= persistence;
totalamplitude += amplitude;
for (i=0; i<WIDTH; i++) {
int j;
for (j=0; j<HEIGHT; j++) {
perlin[i][j] += smooth[octave][i][j] * amplitude;
}
}
}
// normalise
for (i=0; i<WIDTH; i++) {
int j;
for (j=0; j<HEIGHT; j++) {
perlin[i][j] /= totalamplitude;
}
}
}
int main(int argc, char **argv) {
srand(time(NULL));
float m[WIDTH][HEIGHT];
generatewhitenoise(m);
// printmatrix(m, "random\0");
float perlin[WIDTH][HEIGHT];
generateperlinnoise(m, perlin, 6);
matrixtoimage(perlin, "perlinc.png\0");
// int i;
// for (i=0; i<7; i++) {
// generatesmoothnoise(m, smooth, i);
// // printmatrix(smooth, "smooth\0");
// char str[255];
// sprintf(str, "testsmooth%d.png", i);
// matrixtoimage(smooth, str);
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment