├── Makefile ├── misc.h ├── noise.c ├── perlin.c ├── perlin.h ├── simplex.c └── simplex.h /Makefile: -------------------------------------------------------------------------------- 1 | 2 | RM = rm 3 | CC = gcc -std=gnu99 4 | CFLAGS = -Wall -O3 -march=core2 -pipe 5 | LDFLAGS = 6 | 7 | ifdef PROFILE 8 | CFLAGS += -g 9 | LDFLAGS += -pg 10 | endif 11 | 12 | noise: noise.c perlin.c simplex.c 13 | $(CC) $(CFLAGS) $(LDFLAGS) -lm `sdl-config --cflags --libs` -lGL -o $@ $^ 14 | 15 | .PHONY: clean 16 | clean: 17 | $(RM) -f perlin simplex 18 | -------------------------------------------------------------------------------- /misc.h: -------------------------------------------------------------------------------- 1 | /* misc.h*/ 2 | 3 | #ifndef _MISC_H 4 | #define _MISC_H 5 | 6 | #define max(x,y) (((x) > (y)) ? (x) : (y)) 7 | #define min(x,y) (((x) < (y)) ? (x) : (y)) 8 | 9 | #define FASTFLOOR(x) (((x) >= 0) ? (int)(x) : (int)(x)-1) 10 | 11 | #endif /* !_MISC_H */ 12 | -------------------------------------------------------------------------------- /noise.c: -------------------------------------------------------------------------------- 1 | /* noise.c */ 2 | 3 | #include "SDL.h" 4 | #include "SDL_opengl.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "perlin.h" 11 | #include "simplex.h" 12 | #include "misc.h" 13 | 14 | 15 | #define WIDTH 256 16 | #define HEIGHT 256 17 | #define SCALE 2 18 | #define USE_RECT_TEX 0 19 | 20 | #define GL_CHECK_ERROR(s) do { if (glGetError() != GL_NO_ERROR) { fprintf(stderr, "%s: Error at line %i in %s\n", (s), __LINE__, __FILE__); abort(); } } while (0) 21 | 22 | 23 | typedef float (*noise3d_func)(float x, float y, float z); 24 | 25 | 26 | static float __attribute__ ((const)) 27 | lerp(float a, float b, float t) 28 | { 29 | return (1-t)*a + t*b; 30 | } 31 | 32 | static unsigned int __attribute__ ((const)) 33 | rgba_f_to_i(float r, float g, float b, float a) 34 | { 35 | unsigned int cr = (unsigned int)(0xff*r) & 0xff; 36 | unsigned int cg = (unsigned int)(0xff*g) & 0xff; 37 | unsigned int cb = (unsigned int)(0xff*b) & 0xff; 38 | unsigned int ca = (unsigned int)(0xff*a) & 0xff; 39 | return (ca << 24) | (cb << 16) | (cg << 8) | cr; 40 | } 41 | 42 | /* Blue */ 43 | static const float color_grad[][5] = { 44 | { 0.0, 0.0, 0.0, 1.0, 0.3 }, 45 | { 0.0, 0.0, 0.25, 1.0, 0.45 }, 46 | { 0.2, 0.13, 0.93, 1.0, 0.25 }, 47 | { 1.0, 1.0, 1.0, 1.0, 0.0 } 48 | }; 49 | 50 | /* Red */ 51 | /* 52 | static const float color_grad[][5] = { 53 | { 1.0, 1.0, 1.0, 1.0, 0.3 }, 54 | { 0.95, 0.95, 0.0, 1.0, 0.25 }, 55 | { 0.75, 0.35, 0.0, 1.0, 0.45 }, 56 | { 0.0, 0.0, 0.0, 1.0, 0.0 } 57 | }; 58 | */ 59 | 60 | static unsigned int 61 | rgba_map(float v) 62 | { 63 | float r, g, b, a; 64 | 65 | int j = 1; 66 | float s = 0.0; 67 | while (1) { 68 | if (v < s+color_grad[j-1][4]) { 69 | r = lerp(color_grad[j-1][0], color_grad[j][0], (v-s)/color_grad[j-1][4]); 70 | g = lerp(color_grad[j-1][1], color_grad[j][1], (v-s)/color_grad[j-1][4]); 71 | b = lerp(color_grad[j-1][2], color_grad[j][2], (v-s)/color_grad[j-1][4]); 72 | a = lerp(color_grad[j-1][3], color_grad[j][3], (v-s)/color_grad[j-1][4]); 73 | break; 74 | } 75 | 76 | if (color_grad[j][4] == 0.0) { 77 | r = color_grad[j][0]; 78 | g = color_grad[j][1]; 79 | b = color_grad[j][2]; 80 | a = color_grad[j][3]; 81 | break; 82 | } 83 | 84 | s += color_grad[j-1][4]; 85 | j += 1; 86 | } 87 | 88 | return rgba_f_to_i(r, g, b, a); 89 | } 90 | 91 | #define GRAD_WIDTH 256 92 | 93 | unsigned int rgba_grad[GRAD_WIDTH]; 94 | 95 | static void 96 | rgba_gradient() 97 | { 98 | for (int i = 0; i < GRAD_WIDTH; i++) rgba_grad[i] = rgba_map((float)i/(GRAD_WIDTH-1)); 99 | } 100 | 101 | static void 102 | perlin_map_rgb(unsigned int dest[], const float src[]) 103 | { 104 | for (int i = 0; i < WIDTH*HEIGHT; i++) dest[i] = rgba_grad[FASTFLOOR(src[i]*(GRAD_WIDTH-1))]; 105 | } 106 | 107 | 108 | static void 109 | setup_sdl() 110 | { 111 | const SDL_VideoInfo* video; 112 | 113 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 114 | fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); 115 | exit(1); 116 | } 117 | 118 | atexit(SDL_Quit); 119 | 120 | video = SDL_GetVideoInfo(); 121 | if (!video) { 122 | fprintf(stderr, "Couldn't get video information: %s\n", SDL_GetError()); 123 | exit(1); 124 | } 125 | 126 | /* Set the minimum requirements for the OpenGL window */ 127 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); 128 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); 129 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); 130 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); 131 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 132 | 133 | /* Note the SDL_DOUBLEBUF flag is not required to enable double 134 | * buffering when setting an OpenGL video mode. 135 | * Double buffering is enabled or disabled using the 136 | * SDL_GL_DOUBLEBUFFER attribute. 137 | */ 138 | if (SDL_SetVideoMode(SCALE*WIDTH, SCALE*HEIGHT+SCALE*50, video->vfmt->BitsPerPixel, SDL_OPENGL) == 0) { 139 | fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError()); 140 | exit(1); 141 | } 142 | } 143 | 144 | static void 145 | setup_opengl() 146 | { 147 | glEnable(GL_TEXTURE_2D); 148 | GL_CHECK_ERROR("glEnable"); 149 | 150 | if (USE_RECT_TEX) { 151 | glEnable(GL_TEXTURE_RECTANGLE_ARB); 152 | GL_CHECK_ERROR("glEnable"); 153 | } 154 | 155 | glClearColor(0, 0, 0, 0); 156 | GL_CHECK_ERROR("glClearColor"); 157 | 158 | glViewport(0, 0, SCALE*WIDTH, SCALE*HEIGHT+SCALE*50); 159 | GL_CHECK_ERROR("glViewport"); 160 | 161 | glClear(GL_COLOR_BUFFER_BIT); 162 | GL_CHECK_ERROR("glClear"); 163 | 164 | glMatrixMode(GL_PROJECTION); 165 | GL_CHECK_ERROR("glMatrixMode"); 166 | glLoadIdentity(); 167 | GL_CHECK_ERROR("glLoadIdentity"); 168 | 169 | glOrtho(0, SCALE*WIDTH, SCALE*HEIGHT+SCALE*50, 0, -1, 1); 170 | GL_CHECK_ERROR("glOrtho"); 171 | 172 | glMatrixMode(GL_MODELVIEW); 173 | GL_CHECK_ERROR("glMatrixMode"); 174 | glLoadIdentity(); 175 | GL_CHECK_ERROR("glLoadIdentity"); 176 | } 177 | 178 | GLuint textures[2]; 179 | 180 | static void 181 | repaint() 182 | { 183 | /* Bind noise texture */ 184 | glBindTexture(GL_TEXTURE_2D, textures[0]); 185 | GL_CHECK_ERROR("glBindTextures"); 186 | 187 | if (USE_RECT_TEX) { 188 | glBegin(GL_QUADS); 189 | glTexCoord2i(0, 0); 190 | glVertex2f(0, 0); 191 | 192 | glTexCoord2i(WIDTH, 0); 193 | glVertex2f(SCALE*WIDTH, 0); 194 | 195 | glTexCoord2i(WIDTH, HEIGHT); 196 | glVertex2f(SCALE*WIDTH, SCALE*HEIGHT); 197 | 198 | glTexCoord2i(0, HEIGHT); 199 | glVertex2f(0, SCALE*HEIGHT); 200 | glEnd(); 201 | } else { 202 | glBegin(GL_QUADS); 203 | glTexCoord2i(0, 0); 204 | glVertex2f(0, 0); 205 | 206 | glTexCoord2i(1, 0); 207 | glVertex2f(SCALE*WIDTH, 0); 208 | 209 | glTexCoord2i(1, 1); 210 | glVertex2f(SCALE*WIDTH, SCALE*HEIGHT); 211 | 212 | glTexCoord2i(0, 1); 213 | glVertex2f(0, SCALE*HEIGHT); 214 | glEnd(); 215 | } 216 | 217 | /* Bind histogram texture */ 218 | glBindTexture(GL_TEXTURE_2D, textures[1]); 219 | GL_CHECK_ERROR("glBindTextures"); 220 | 221 | glBegin(GL_QUADS); 222 | glTexCoord2i(0, 0); 223 | glVertex2f(0, SCALE*HEIGHT); 224 | 225 | glTexCoord2i(1, 0); 226 | glVertex2f(SCALE*WIDTH, SCALE*HEIGHT); 227 | 228 | glTexCoord2i(1, 1); 229 | glVertex2f(SCALE*WIDTH, SCALE*HEIGHT+SCALE*50); 230 | 231 | glTexCoord2i(0, 1); 232 | glVertex2f(0, SCALE*HEIGHT+SCALE*50); 233 | glEnd(); 234 | } 235 | 236 | static void 237 | recalculate_noise(noise3d_func noise3d, int type, float z) 238 | { 239 | static float noise[WIDTH*HEIGHT]; 240 | static unsigned int noise_tex[WIDTH*HEIGHT]; 241 | static unsigned int histogram[WIDTH]; 242 | static unsigned int histogram_tex[WIDTH*WIDTH]; 243 | 244 | /* Reset histogram */ 245 | unsigned int histogram_max = 0; 246 | memset(histogram, 0, sizeof(unsigned int)*WIDTH); 247 | 248 | /* Create noise texture */ 249 | for (int y = 0; y < HEIGHT; y++) { 250 | for (int x = 0; x < WIDTH; x++) { 251 | int index = y*WIDTH+x; 252 | switch (type) { 253 | case 0: 254 | noise[index] = noise3d(((float)(1 << 1)*x)/HEIGHT, ((float)(1 << 1)*y)/HEIGHT, z); 255 | noise[index] = 0.5*noise[index] + 0.5; 256 | break; 257 | case 1: 258 | noise[index] = noise3d(((float)(1 << 7)*x)/HEIGHT, ((float)(1 << 6)*y)/HEIGHT, z); 259 | noise[index] = 0.5*noise[index] + 0.5; 260 | break; 261 | case 2: 262 | noise[index] = noise3d(((float)(1 << 8)*x)/HEIGHT, ((float)(1 << 2)*y)/HEIGHT, z); 263 | noise[index] = 0.5*noise[index] + 0.5; 264 | break; 265 | case 3: 266 | noise[index] = noise3d(((float)(1 << 4)*x)/HEIGHT, ((float)(1 << 4)*y)/HEIGHT, z); 267 | noise[index] = 0.5*noise[index] + 0.5; 268 | break; 269 | case 4: 270 | noise[index] = 0; 271 | for (int l = 1; l < 5; l++) { 272 | noise[index] += (1.0/(1 << l))*noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << l)*y)/HEIGHT, z); 273 | } 274 | noise[index] = 0.5 * noise[index] * ((float)(1 << 4))/((float)(1 << 4)-1.0) + 0.5; 275 | break; 276 | case 5: 277 | noise[index] = 0; 278 | for (int l = 1; l < 5; l++) { 279 | noise[index] += (1.0/(1 << l))*noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << (l*l))*y)/HEIGHT, z); 280 | } 281 | noise[index] = 0.5 * noise[index] * ((float)(1 << 4))/((float)(1 << 4)-1.0) + 0.5; 282 | break; 283 | case 6: 284 | noise[index] = 0; 285 | for (int l = 1; l < 5; l++) { 286 | noise[index] += fabs((1.0/(1 << l))*noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << l)*y)/HEIGHT, z)); 287 | } 288 | noise[index] = noise[index] * ((float)(1 << 4))/((float)(1 << 4)-1.0) + 0.25; 289 | break; 290 | case 7: 291 | noise[index] = 0; 292 | for (int l = 1; l < 5; l++) { 293 | noise[index] += fabs((1.0/(1 << l))*noise3d(((float)(1 << ((l % 2) ? l*l : l))*x)/HEIGHT, ((float)(1 << ((l % 2) ? l : l*l))*y)/HEIGHT, z)); 294 | } 295 | noise[index] = noise[index] * ((float)(1 << 4))/((float)(1 << 4)-1.0) + 0.25; 296 | break; 297 | case 8: 298 | noise[index] = 0; 299 | for (int l = 1; l < 5; l++) { 300 | noise[index] += fabs((1.0/(1 << l))*noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << l)*y)/HEIGHT, z)); 301 | } 302 | noise[index] = sinf(-1.0+(1.8*M_PI*y)/HEIGHT + noise[index]); 303 | noise[index] = 0.5*noise[index] + 0.5; 304 | break; 305 | case 9: 306 | noise[index] = 0.0; 307 | for (int l = 1; l < 5; l++) { 308 | noise[index] += sinf(((float)l*M_PI*y)/HEIGHT + ((float)(5-l)*M_PI*x)/WIDTH + fabs(noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << l)*y)/HEIGHT, z))); 309 | } 310 | noise[index] = (1.0/8.0)*noise[index] + 0.5; 311 | break; 312 | case 10: 313 | noise[index] = 0; 314 | for (int l = 2; l < 4; l++) { 315 | noise[index] += fabs((1.0/l)*noise3d(((float)(1 << l)*x)/HEIGHT, ((float)(1 << l)*y)/HEIGHT, z)); 316 | } 317 | noise[index] = sinf(-1.0+(0.8*M_PI*y)/HEIGHT + noise[index]); 318 | noise[index] = 0.5*noise[index] + 0.5; 319 | break; 320 | } 321 | 322 | /* Update histogram */ 323 | unsigned int histogram_index = FASTFLOOR(noise[index]*WIDTH); 324 | histogram_index = min(histogram_index, WIDTH-1); 325 | histogram[histogram_index] += 1; 326 | histogram_max = max(histogram[histogram_index], histogram_max); 327 | } 328 | } 329 | 330 | perlin_map_rgb(noise_tex, noise); 331 | 332 | /* Bind noise texture */ 333 | glBindTexture(GL_TEXTURE_2D, textures[0]); 334 | GL_CHECK_ERROR("glBindTextures"); 335 | 336 | if (USE_RECT_TEX) { 337 | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, noise_tex); 338 | GL_CHECK_ERROR("glTexImage2D"); 339 | } else { 340 | glTexImage2D(GL_TEXTURE_2D, 0, 4, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, noise_tex); 341 | GL_CHECK_ERROR("glTexImage2D"); 342 | } 343 | 344 | /* Create histogram texture */ 345 | for (int y = 0; y < HEIGHT; y++) { 346 | for (int x = 0; x < WIDTH; x++) { 347 | int index = y*WIDTH+x; 348 | if (histogram[x]/8.0 > HEIGHT-y) histogram_tex[index] = rgba_map((x)/(float)WIDTH); 349 | else histogram_tex[index] = rgba_f_to_i(0.03, 0.03, 0.03, 1.0); 350 | } 351 | } 352 | 353 | /* Bind histogram texture */ 354 | glBindTexture(GL_TEXTURE_2D, textures[1]); 355 | GL_CHECK_ERROR("glBindTextures"); 356 | 357 | glTexImage2D(GL_TEXTURE_2D, 0, 4, WIDTH, WIDTH, 0, GL_RGBA, GL_UNSIGNED_BYTE, histogram_tex); 358 | } 359 | 360 | #define FPS_LIMIT 25 361 | 362 | static void 363 | main_loop() 364 | { 365 | /* FPS */ 366 | int fps = 0; 367 | int fps_ema = 0; 368 | int fps_ticks_delta = 0; 369 | int fps_ticks_delta_ema = 0; 370 | const float ema_alpha = 0.05; 371 | 372 | int type = 0; 373 | noise3d_func f = perlin3d; 374 | printf("Perlin noise\n"); 375 | 376 | unsigned int t = 0; 377 | SDL_Event event; 378 | while (1) { 379 | /* process pending events */ 380 | while (SDL_PollEvent(&event)) { 381 | switch (event.type) { 382 | case SDL_QUIT: 383 | exit(0); 384 | break; 385 | case SDL_KEYDOWN: 386 | if (event.key.keysym.sym == SDLK_SPACE) { 387 | type = (type + 1) % 11; 388 | } else if (event.key.keysym.sym == SDLK_n) { 389 | if (f == perlin3d) { 390 | f = simplex3d; 391 | printf("Simplex noise\n"); 392 | } else { 393 | f = perlin3d; 394 | printf("Perlin noise\n"); 395 | } 396 | } 397 | break; 398 | } 399 | } 400 | 401 | unsigned int before = SDL_GetTicks(); 402 | 403 | /* update the screen */ 404 | recalculate_noise(f, type, (10.0*t)/512); 405 | repaint(); 406 | SDL_GL_SwapBuffers(); 407 | t += 1; 408 | 409 | /* FPS */ 410 | unsigned int now = SDL_GetTicks(); 411 | fps_ticks_delta = now - before; 412 | fps = 1000 / fps_ticks_delta; 413 | if (fps_ema) fps_ema = ema_alpha*fps + (1-ema_alpha)*fps_ema; 414 | else fps_ema = fps; 415 | if (fps_ticks_delta_ema) fps_ticks_delta_ema = ema_alpha*fps_ticks_delta + (1-ema_alpha)*fps_ticks_delta; 416 | else fps_ticks_delta_ema = fps_ticks_delta; 417 | 418 | if (t % 50 == 0) printf("fps: %i, fps_ema: %i, delta_ema: %i\n", fps, fps_ema, fps_ticks_delta_ema); 419 | 420 | unsigned int frame_time = 1000 / FPS_LIMIT; 421 | if (frame_time > fps_ticks_delta) SDL_Delay(frame_time - fps_ticks_delta); 422 | } 423 | } 424 | 425 | int 426 | main(int argc, char* argv[]) 427 | { 428 | setup_sdl(); 429 | setup_opengl(); 430 | 431 | rgba_gradient(); 432 | 433 | /* Generate GL texture */ 434 | glGenTextures(2, textures); 435 | GL_CHECK_ERROR("glGenTextures"); 436 | 437 | /* Bind noise texture */ 438 | glBindTexture(GL_TEXTURE_2D, textures[0]); 439 | GL_CHECK_ERROR("glBindTextures"); 440 | 441 | /* Set parameters */ 442 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 443 | GL_CHECK_ERROR("glTexParameteri"); 444 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 445 | GL_CHECK_ERROR("glTexParameteri"); 446 | 447 | /* Bind histogram texture */ 448 | glBindTexture(GL_TEXTURE_2D, textures[1]); 449 | GL_CHECK_ERROR("glBindTextures"); 450 | 451 | /* Set parameters */ 452 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 453 | GL_CHECK_ERROR("glTexParameteri"); 454 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 455 | GL_CHECK_ERROR("glTexParameteri"); 456 | 457 | main_loop(); 458 | 459 | return 0; 460 | } 461 | -------------------------------------------------------------------------------- /perlin.c: -------------------------------------------------------------------------------- 1 | /* perlin.c */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "misc.h" 8 | 9 | 10 | static const char grad3[][3] = { 11 | { 1, 1, 0 }, { -1, 1, 0 }, { 1, -1, 0 }, { -1, -1, 0 }, 12 | { 1, 0, 1 }, { -1, 0, 1 }, { 1, 0, -1 }, { -1, 0, -1 }, 13 | { 0, 1, 1 }, { 0, -1, 1 }, { 0, 1, -1 }, { 0, -1, -1 } 14 | }; 15 | 16 | static const unsigned char perm[] = { 17 | 182, 232, 51, 15, 55, 119, 7, 107, 230, 227, 6, 34, 216, 61, 183, 36, 18 | 40, 134, 74, 45, 157, 78, 81, 114, 145, 9, 209, 189, 147, 58, 126, 0, 19 | 240, 169, 228, 235, 67, 198, 72, 64, 88, 98, 129, 194, 99, 71, 30, 127, 20 | 18, 150, 155, 179, 132, 62, 116, 200, 251, 178, 32, 140, 130, 139, 250, 26, 21 | 151, 203, 106, 123, 53, 255, 75, 254, 86, 234, 223, 19, 199, 244, 241, 1, 22 | 172, 70, 24, 97, 196, 10, 90, 246, 252, 68, 84, 161, 236, 205, 80, 91, 23 | 233, 225, 164, 217, 239, 220, 20, 46, 204, 35, 31, 175, 154, 17, 133, 117, 24 | 73, 224, 125, 65, 77, 173, 3, 2, 242, 221, 120, 218, 56, 190, 166, 11, 25 | 138, 208, 231, 50, 135, 109, 213, 187, 152, 201, 47, 168, 185, 186, 167, 165, 26 | 102, 153, 156, 49, 202, 69, 195, 92, 21, 229, 63, 104, 197, 136, 148, 94, 27 | 171, 93, 59, 149, 23, 144, 160, 57, 76, 141, 96, 158, 163, 219, 237, 113, 28 | 206, 181, 112, 111, 191, 137, 207, 215, 13, 83, 238, 249, 100, 131, 118, 243, 29 | 162, 248, 43, 66, 226, 27, 211, 95, 214, 105, 108, 101, 170, 128, 210, 87, 30 | 38, 44, 174, 188, 176, 39, 14, 143, 159, 16, 124, 222, 33, 247, 37, 245, 31 | 8, 4, 22, 82, 110, 180, 184, 12, 25, 5, 193, 41, 85, 177, 192, 253, 32 | 79, 29, 115, 103, 142, 146, 52, 48, 89, 54, 121, 212, 122, 60, 28, 42, 33 | 34 | 182, 232, 51, 15, 55, 119, 7, 107, 230, 227, 6, 34, 216, 61, 183, 36, 35 | 40, 134, 74, 45, 157, 78, 81, 114, 145, 9, 209, 189, 147, 58, 126, 0, 36 | 240, 169, 228, 235, 67, 198, 72, 64, 88, 98, 129, 194, 99, 71, 30, 127, 37 | 18, 150, 155, 179, 132, 62, 116, 200, 251, 178, 32, 140, 130, 139, 250, 26, 38 | 151, 203, 106, 123, 53, 255, 75, 254, 86, 234, 223, 19, 199, 244, 241, 1, 39 | 172, 70, 24, 97, 196, 10, 90, 246, 252, 68, 84, 161, 236, 205, 80, 91, 40 | 233, 225, 164, 217, 239, 220, 20, 46, 204, 35, 31, 175, 154, 17, 133, 117, 41 | 73, 224, 125, 65, 77, 173, 3, 2, 242, 221, 120, 218, 56, 190, 166, 11, 42 | 138, 208, 231, 50, 135, 109, 213, 187, 152, 201, 47, 168, 185, 186, 167, 165, 43 | 102, 153, 156, 49, 202, 69, 195, 92, 21, 229, 63, 104, 197, 136, 148, 94, 44 | 171, 93, 59, 149, 23, 144, 160, 57, 76, 141, 96, 158, 163, 219, 237, 113, 45 | 206, 181, 112, 111, 191, 137, 207, 215, 13, 83, 238, 249, 100, 131, 118, 243, 46 | 162, 248, 43, 66, 226, 27, 211, 95, 214, 105, 108, 101, 170, 128, 210, 87, 47 | 38, 44, 174, 188, 176, 39, 14, 143, 159, 16, 124, 222, 33, 247, 37, 245, 48 | 8, 4, 22, 82, 110, 180, 184, 12, 25, 5, 193, 41, 85, 177, 192, 253, 49 | 79, 29, 115, 103, 142, 146, 52, 48, 89, 54, 121, 212, 122, 60, 28, 42 50 | }; 51 | 52 | 53 | static float __attribute__ ((pure)) 54 | dot3(const char a[], float x, float y, float z) 55 | { 56 | return a[0]*x + a[1]*y + a[2]*z; 57 | } 58 | 59 | static float __attribute__ ((const)) 60 | lerp(float a, float b, float t) 61 | { 62 | return (1-t)*a + t*b; 63 | } 64 | 65 | static float __attribute__ ((const)) 66 | fade(float t) 67 | { 68 | return t*t*t*(t*(t*6-15)+10); 69 | } 70 | 71 | float __attribute__ ((pure)) 72 | perlin3d(float x, float y, float z) 73 | { 74 | /* Find grid points */ 75 | int gx = FASTFLOOR(x); 76 | int gy = FASTFLOOR(y); 77 | int gz = FASTFLOOR(z); 78 | 79 | /* Relative coords within grid cell */ 80 | float rx = x - gx; 81 | float ry = y - gy; 82 | float rz = z - gz; 83 | 84 | /* Wrap cell coords */ 85 | gx = gx & 255; 86 | gy = gy & 255; 87 | gz = gz & 255; 88 | 89 | /* Calculate gradient indices */ 90 | unsigned int gi[8]; 91 | for (int i = 0; i < 8; i++) gi[i] = perm[gx+((i>>2)&1)+perm[gy+((i>>1)&1)+perm[gz+(i&1)]]] % 12; 92 | 93 | /* Noise contribution from each corner */ 94 | float n[8]; 95 | for (int i = 0; i < 8; i++) n[i] = dot3(grad3[gi[i]], rx - ((i>>2)&1), ry - ((i>>1)&1), rz - (i&1)); 96 | 97 | /* Fade curves */ 98 | float u = fade(rx); 99 | float v = fade(ry); 100 | float w = fade(rz); 101 | 102 | /* Interpolate */ 103 | float nx[4]; 104 | for (int i = 0; i < 4; i++) nx[i] = lerp(n[i], n[4+i], u); 105 | 106 | float nxy[2]; 107 | for (int i = 0; i < 2; i++) nxy[i] = lerp(nx[i], nx[2+i], v); 108 | 109 | return lerp(nxy[0], nxy[1], w); 110 | } 111 | -------------------------------------------------------------------------------- /perlin.h: -------------------------------------------------------------------------------- 1 | /* perlin.h */ 2 | 3 | #ifndef _PERLIN_H 4 | #define _PERLIN_H 5 | 6 | float __attribute__ ((pure)) 7 | perlin3d(float x, float y, float z); 8 | 9 | #endif /* !_PERLIN_H */ 10 | -------------------------------------------------------------------------------- /simplex.c: -------------------------------------------------------------------------------- 1 | /* simplex.c */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "misc.h" 8 | 9 | 10 | static const float grad3[][3] = { 11 | { 1, 1, 0 }, { -1, 1, 0 }, { 1, -1, 0 }, { -1, -1, 0 }, 12 | { 1, 0, 1 }, { -1, 0, 1 }, { 1, 0, -1 }, { -1, 0, -1 }, 13 | { 0, 1, 1 }, { 0, -1, 1 }, { 0, 1, -1 }, { 0, -1, -1 } 14 | }; 15 | 16 | static const unsigned int perm[] = { 17 | 182, 232, 51, 15, 55, 119, 7, 107, 230, 227, 6, 34, 216, 61, 183, 36, 18 | 40, 134, 74, 45, 157, 78, 81, 114, 145, 9, 209, 189, 147, 58, 126, 0, 19 | 240, 169, 228, 235, 67, 198, 72, 64, 88, 98, 129, 194, 99, 71, 30, 127, 20 | 18, 150, 155, 179, 132, 62, 116, 200, 251, 178, 32, 140, 130, 139, 250, 26, 21 | 151, 203, 106, 123, 53, 255, 75, 254, 86, 234, 223, 19, 199, 244, 241, 1, 22 | 172, 70, 24, 97, 196, 10, 90, 246, 252, 68, 84, 161, 236, 205, 80, 91, 23 | 233, 225, 164, 217, 239, 220, 20, 46, 204, 35, 31, 175, 154, 17, 133, 117, 24 | 73, 224, 125, 65, 77, 173, 3, 2, 242, 221, 120, 218, 56, 190, 166, 11, 25 | 138, 208, 231, 50, 135, 109, 213, 187, 152, 201, 47, 168, 185, 186, 167, 165, 26 | 102, 153, 156, 49, 202, 69, 195, 92, 21, 229, 63, 104, 197, 136, 148, 94, 27 | 171, 93, 59, 149, 23, 144, 160, 57, 76, 141, 96, 158, 163, 219, 237, 113, 28 | 206, 181, 112, 111, 191, 137, 207, 215, 13, 83, 238, 249, 100, 131, 118, 243, 29 | 162, 248, 43, 66, 226, 27, 211, 95, 214, 105, 108, 101, 170, 128, 210, 87, 30 | 38, 44, 174, 188, 176, 39, 14, 143, 159, 16, 124, 222, 33, 247, 37, 245, 31 | 8, 4, 22, 82, 110, 180, 184, 12, 25, 5, 193, 41, 85, 177, 192, 253, 32 | 79, 29, 115, 103, 142, 146, 52, 48, 89, 54, 121, 212, 122, 60, 28, 42, 33 | 34 | 182, 232, 51, 15, 55, 119, 7, 107, 230, 227, 6, 34, 216, 61, 183, 36, 35 | 40, 134, 74, 45, 157, 78, 81, 114, 145, 9, 209, 189, 147, 58, 126, 0, 36 | 240, 169, 228, 235, 67, 198, 72, 64, 88, 98, 129, 194, 99, 71, 30, 127, 37 | 18, 150, 155, 179, 132, 62, 116, 200, 251, 178, 32, 140, 130, 139, 250, 26, 38 | 151, 203, 106, 123, 53, 255, 75, 254, 86, 234, 223, 19, 199, 244, 241, 1, 39 | 172, 70, 24, 97, 196, 10, 90, 246, 252, 68, 84, 161, 236, 205, 80, 91, 40 | 233, 225, 164, 217, 239, 220, 20, 46, 204, 35, 31, 175, 154, 17, 133, 117, 41 | 73, 224, 125, 65, 77, 173, 3, 2, 242, 221, 120, 218, 56, 190, 166, 11, 42 | 138, 208, 231, 50, 135, 109, 213, 187, 152, 201, 47, 168, 185, 186, 167, 165, 43 | 102, 153, 156, 49, 202, 69, 195, 92, 21, 229, 63, 104, 197, 136, 148, 94, 44 | 171, 93, 59, 149, 23, 144, 160, 57, 76, 141, 96, 158, 163, 219, 237, 113, 45 | 206, 181, 112, 111, 191, 137, 207, 215, 13, 83, 238, 249, 100, 131, 118, 243, 46 | 162, 248, 43, 66, 226, 27, 211, 95, 214, 105, 108, 101, 170, 128, 210, 87, 47 | 38, 44, 174, 188, 176, 39, 14, 143, 159, 16, 124, 222, 33, 247, 37, 245, 48 | 8, 4, 22, 82, 110, 180, 184, 12, 25, 5, 193, 41, 85, 177, 192, 253, 49 | 79, 29, 115, 103, 142, 146, 52, 48, 89, 54, 121, 212, 122, 60, 28, 42 50 | }; 51 | 52 | 53 | static float 54 | dot3(const float a[], float x, float y, float z) 55 | { 56 | return a[0]*x + a[1]*y + a[2]*z; 57 | } 58 | 59 | #define FASTFLOOR(x) (((x) >= 0) ? (int)(x) : (int)(x)-1) 60 | 61 | float __attribute__ ((pure)) 62 | simplex3d(float x, float y, float z) 63 | { 64 | /* Skew input space */ 65 | float s = (x+y+z)*(1.0/3.0); 66 | int i = FASTFLOOR(x+s); 67 | int j = FASTFLOOR(y+s); 68 | int k = FASTFLOOR(z+s); 69 | 70 | /* Unskew */ 71 | float t = (float)(i+j+k)*(1.0/6.0); 72 | float gx0 = i-t; 73 | float gy0 = j-t; 74 | float gz0 = k-t; 75 | float x0 = x-gx0; 76 | float y0 = y-gy0; 77 | float z0 = z-gz0; 78 | 79 | /* Determine simplex */ 80 | int i1, j1, k1; 81 | int i2, j2, k2; 82 | 83 | if (x0 >= y0) { 84 | if (y0 >= z0) { 85 | i1 = 1; j1 = 0; k1 = 0; 86 | i2 = 1; j2 = 1; k2 = 0; 87 | } else if (x0 >= z0) { 88 | i1 = 1; j1 = 0; k1 = 0; 89 | i2 = 1; j2 = 0; k2 = 1; 90 | } else { 91 | i1 = 0; j1 = 0; k1 = 1; 92 | i2 = 1; j2 = 0; k2 = 1; 93 | } 94 | } else { 95 | if (y0 < z0) { 96 | i1 = 0; j1 = 0; k1 = 1; 97 | i2 = 0; j2 = 1; k2 = 1; 98 | } else if (x0 < z0) { 99 | i1 = 0; j1 = 1; k1 = 0; 100 | i2 = 0; j2 = 1; k2 = 1; 101 | } else { 102 | i1 = 0; j1 = 1; k1 = 0; 103 | i2 = 1; j2 = 1; k2 = 0; 104 | } 105 | } 106 | 107 | /* Calculate offsets in x,y,z coords */ 108 | float x1 = x0 - i1 + (1.0/6.0); 109 | float y1 = y0 - j1 + (1.0/6.0); 110 | float z1 = z0 - k1 + (1.0/6.0); 111 | float x2 = x0 - i2 + 2.0*(1.0/6.0); 112 | float y2 = y0 - j2 + 2.0*(1.0/6.0); 113 | float z2 = z0 - k2 + 2.0*(1.0/6.0); 114 | float x3 = x0 - 1.0 + 3.0*(1.0/6.0); 115 | float y3 = y0 - 1.0 + 3.0*(1.0/6.0); 116 | float z3 = z0 - 1.0 + 3.0*(1.0/6.0); 117 | 118 | int ii = i % 256; 119 | int jj = j % 256; 120 | int kk = k % 256; 121 | 122 | /* Calculate gradient incides */ 123 | int gi0 = perm[ii+perm[jj+perm[kk]]] % 12; 124 | int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1]]] % 12; 125 | int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2]]] % 12; 126 | int gi3 = perm[ii+1+perm[jj+1+perm[kk+1]]] % 12; 127 | 128 | /* Calculate contributions */ 129 | float n0, n1, n2, n3; 130 | 131 | float t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; 132 | if (t0 < 0) n0 = 0.0; 133 | else { 134 | t0 *= t0; 135 | n0 = t0 * t0 * dot3(grad3[gi0], x0, y0, z0); 136 | } 137 | 138 | float t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; 139 | if (t1 < 0) n1 = 0.0; 140 | else { 141 | t1 *= t1; 142 | n1 = t1 * t1 * dot3(grad3[gi1], x1, y1, z1); 143 | } 144 | 145 | float t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; 146 | if (t2 < 0) n2 = 0.0; 147 | else { 148 | t2 *= t2; 149 | n2 = t2 * t2 * dot3(grad3[gi2], x2, y2, z2); 150 | } 151 | 152 | float t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; 153 | if (t3 < 0) n3 = 0.0; 154 | else { 155 | t3 *= t3; 156 | n3 = t3 * t3 * dot3(grad3[gi3], x3, y3, z3); 157 | } 158 | 159 | /* Return scaled sum of contributions */ 160 | return 32.0*(n0 + n1 + n2 + n3); 161 | } 162 | -------------------------------------------------------------------------------- /simplex.h: -------------------------------------------------------------------------------- 1 | /* simplex.h */ 2 | 3 | #ifndef _SIMPLEX_H 4 | #define _SIMPLEX_H 5 | 6 | float __attribute__ ((pure)) 7 | simplex3d(float x, float y, float z); 8 | 9 | #endif /* !_SIMPLEX_H */ 10 | --------------------------------------------------------------------------------