diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.md | 5 | ||||
| -rw-r--r-- | graphics.c | 6 | ||||
| -rw-r--r-- | header.h | 8 | ||||
| -rw-r--r-- | helper.c | 50 | ||||
| -rw-r--r-- | mandelbrot.c | 36 |
6 files changed, 85 insertions, 22 deletions
@@ -1,7 +1,7 @@ NAME = mandel CC = gcc CCFLAGS = -Wall -Wextra -LDFLAGS = -lpthread $(shell sdl2-config --libs --cflags) +LDFLAGS = -lm -lpthread $(shell sdl2-config --libs --cflags) HEADER = header.h SRC = main.c graphics.c mandelbrot.c helper.c @@ -17,10 +17,13 @@ SDL2: `sudo apt install libsdl2-dev` ## TODO -- [ ] Create color spectrum. +- [ ] Color gradient with control points and cubic iterpolation + like <https://stackoverflow.com/a/25816111> - [ ] Smooth shading for out of set iteration colors. - [ ] Draw to bmp image. - [x] Create pixel array and update the render line by line. - [ ] Display coordinates and other useful info. - [x] Computation done in parallel. - [x] Command line options +- [x] Anti-aliasing with supersampling +- [ ] Other (not random?) supersampling algorithm @@ -17,6 +17,8 @@ #define IN_SET_COLOR 0x050505 #define PALETTE_START 0x000022 #define PALETTE_END 0xd62f2f +/* #define PALETTE_START 0x000000 */ +/* #define PALETTE_END 0xffffff */ #define SET_DRAW_COLOR(renderer, c) ( \ SDL_SetRenderDrawColor(renderer, c.rgb.r, c.rgb.g, c.rgb.b, SDL_ALPHA_OPAQUE)); @@ -185,7 +187,7 @@ static void event_handler(GState *state) zoom_out(state, ZOOM_RATIO); break; case SDL_MOUSEBUTTONDOWN: - printf("> %d, %d\n", e.button.x, e.button.y); + /* printf("> %d, %d\n", e.button.x, e.button.y); */ if (e.button.button == SDL_BUTTON_RIGHT) recenter(state, e.button.x, e.button.y); // TODO @@ -222,6 +224,8 @@ static void event_handler(GState *state) return NULL; for (int i = 0; i < MAX_ITERATION; i++) { + /* palette[i] = helper_HSL_to_RGB(i, 0.6, 1.0); */ + /* printf("%x\n", palette[i].hexcode); */ palette[i].rgb.r = i * red_step + start.rgb.r; palette[i].rgb.g = i * green_step + start.rgb.g; palette[i].rgb.b = i * blue_step + start.rgb.b; @@ -4,8 +4,8 @@ # include <stdbool.h> # include <SDL2/SDL.h> -# define MAX_ITERATION 210 -# define ESCAPE_RADIUS 2 +# define MAX_ITERATION 200 +# define ESCAPE_RADIUS 10 # define ESCAPE_RADIUS_SQUARED (ESCAPE_RADIUS * ESCAPE_RADIUS) # define PIXELS_CHANELS 3 @@ -62,6 +62,7 @@ typedef struct { double real_lo; double real_hi; + double imag_step; int width; double imag; Color *palette; @@ -81,6 +82,7 @@ void graphics_run(GState *state); // helper.c double map_range(double x, double src_lo, double src_hi, double dest_lo, double dest_hi); -int *inclusive_range(int start, int end); +Color helper_HSL_to_RGB(int hue, double saturation, double lightness); +double double_rand(void); #endif @@ -1,22 +1,48 @@ #include <math.h> #include "header.h" +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#define MIN3(x, y, z) (MIN(x, MIN(y, z))) + double map_range(double x, double src_lo, double src_hi, double dest_lo, double dest_hi) { - double src_len = fabs(src_hi - src_lo); - double dest_len = fabs(dest_hi - dest_lo); - + double src_len = src_hi - src_lo; + double dest_len = dest_hi - dest_lo; return (x - src_lo) / src_len * dest_len + dest_lo; } -int *inclusive_range(int start, int end) +Color helper_HSL_to_RGB(int hue, double saturation, double lightness) +{ + /* double chroma = (1 - fabs(2 * lightness - 1)) * saturation; */ + /* int hue_p = hue / 60; */ + /* double x = chroma * (1 - abs(hue_p % 2 - 1)); */ + Color color; + + /* if (hue == 0) */ + /* { */ + /* color.hexcode = 0x000000; */ + /* return color; */ + /* } */ + /* */ + /* if (hue_p */ + + double a = saturation * MIN(lightness, 1 - lightness); + int kn0 = (0 + hue / 30) % 12; + int kn8 = (8 + hue / 30) % 12; + int kn4 = (4 + hue / 30) % 12; + Byte f0 = lightness - a * MAX(MIN3(kn0 - 3, 9 - kn0, 1), -1); + Byte f8 = lightness - a * MAX(MIN3(kn8 - 3, 9 - kn8, 1), -1); + Byte f4 = lightness - a * MAX(MIN3(kn4 - 3, 9 - kn4, 1), -1); + + color.rgb.r = f0; + color.rgb.g = f8; + color.rgb.b = f4; + + return color; +} + +double double_rand(void) { - if (end < start) - return NULL; - int *range = malloc(sizeof(int) * (end - start + 1)); - if (range == NULL) - return NULL; - for (int i = 0; start < end; i++) - range[i] = start++; - return range; + return (double)rand() / RAND_MAX; } diff --git a/mandelbrot.c b/mandelbrot.c index 1112575..7017a54 100644 --- a/mandelbrot.c +++ b/mandelbrot.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <math.h> #include <pthread.h> #include "header.h" @@ -9,6 +10,7 @@ #define AXIS_DIV 46.0 #define REAL_AXIS_STEP ((PRINT_REAL_HI - PRINT_REAL_LO) / AXIS_DIV) #define IMAG_AXIS_STEP ((PRINT_IMAG_HI - PRINT_IMAG_LO) / AXIS_DIV) +#define SAMPLES 1 #define IN_CHAR '*' #define OUT_CHAR ' ' @@ -37,6 +39,16 @@ int mandelbrot_in_set(double ca, double cb) return n; } + +int mandelbrot_in_set_super_sampled(double ca, double cb, double real_step, double imag_step) +{ + int total = 0; + for (int i = 0; i < SAMPLES; i++) + total += mandelbrot_in_set(ca - (double_rand() * real_step) / 2, + cb - (double_rand() * imag_step) / 2); + return total / SAMPLES; +} + void *mandelbrot_pixels(double real_lo, double real_hi, double imag_lo, double imag_hi, int width, int height, Color *palette) { @@ -55,6 +67,7 @@ void *mandelbrot_pixels(double real_lo, double real_hi, double imag_lo, args->real_hi = real_hi; args->width = width; args->imag = map_range((double)y, 0, height, imag_lo, imag_hi); + args->imag_step = (imag_hi - imag_lo) / (0.5 + (height - 1)); args->palette = palette; args->row = pixels + PIXELS_CHANELS * width * y; pthread_create(&threads[y], NULL, pixel_row, args); @@ -68,13 +81,28 @@ void *mandelbrot_pixels(double real_lo, double real_hi, double imag_lo, static void *pixel_row(void *void_args) { ThreadArgs *args = (ThreadArgs*)void_args; + int iterations; + double real_step = (args->real_hi - args->real_lo) / (0.5 + (args->width - 1)); for (int x = 0; x < args->width; x++) { double a = map_range((double)x, 0, args->width, args->real_lo, args->real_hi); - Color color = args->palette[mandelbrot_in_set(a, args->imag)]; - args->row[x * PIXELS_CHANELS] = color.rgb.r; - args->row[x * PIXELS_CHANELS + 1] = color.rgb.g; - args->row[x * PIXELS_CHANELS + 2] = color.rgb.b; + if (SAMPLES == 1) + iterations = mandelbrot_in_set(a, args->imag); + else + { + iterations = mandelbrot_in_set_super_sampled( + a, args->imag, real_step, args->imag_step); + } + + /* double logBase = 1.0 / log(2.0); */ + /* double logHalfBase = log(0.5) * logBase; */ + /* int color_index = (int)(5 + iterations - logHalfBase */ + /* - log(log(a * a + args->imag * args->imag)) * logBase); */ + Color color = args->palette[iterations]; + int row_index = x * PIXELS_CHANELS; + args->row[row_index] = color.rgb.r; + args->row[row_index + 1] = color.rgb.g; + args->row[row_index + 2] = color.rgb.b; } free(args); return NULL; |
