From 6d4c3864e3b742a92e9874f1e4dfe3a9c1565188 Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 22 May 2020 10:44:49 +0200 Subject: Added information (iterations, center, time) --- Makefile | 5 +++-- README.md | 28 +++++++--------------------- font/00_starmap.ttf | Bin 0 -> 25056 bytes font/noto_mono_regular.ttf | Bin 0 -> 107848 bytes inc/mandel.h | 26 ++++++++++++++++++++++++-- src/event.c | 31 +++++++++++++++++++++++++++++-- src/state.c | 30 ++++++++++++++++++++++++------ src/text.c | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 33 deletions(-) create mode 100644 font/00_starmap.ttf create mode 100644 font/noto_mono_regular.ttf create mode 100644 src/text.c diff --git a/Makefile b/Makefile index e6c83dc..5ee5d60 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,8 @@ OBJ_DIR = obj CC = gcc OFLAG = -Ofast -funroll-loops -ffast-math CCFLAGS = -I$(INC_DIR) -Wall -Wextra $(OFLAG) -LDFLAGS = -lm -lpthread $(shell sdl2-config --libs --cflags) +LDFLAGS = -lm -lpthread \ + $(shell pkg-config --libs --cflags sdl2 SDL2_ttf) INC = $(shell find $(INC_DIR) -type f -name '*.h') SRC = $(shell find $(SRC_DIR) -type f -name '*.c') @@ -23,7 +24,7 @@ prebuild: $(NAME): $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(HEADER) +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC) $(CC) $(CCFLAGS) -c -o $@ $< debug: OFLAG = -g diff --git a/README.md b/README.md index 0cae1d4..b92d9c9 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,15 @@ -# Mandelbrot set visualizer +# Mandelbrot set visualizer (CPU version) -A visualizer for the [Mandelbrot Set](https://en.wikipedia.org/wiki/Mandelbrot_set). +A visualizer of the [Mandelbrot Set](https://en.wikipedia.org/wiki/Mandelbrot_set). +All computation are on the CPU compared to my [other mandelbrot visualizer](https://github.com/HappyTramp/mandel) where I use the GPU. ## Dependencies - [SDL2](https://www.libsdl.org/) for the graphics -## Install - -SDL2: `sudo apt install libsdl2-dev` - ## Usage -1. compile: `make all` -2. run: `./mandel` - -## TODO - -- [ ] Color gradient with control points and cubic iterpolation - like -- [ ] 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 +``` +make all +./mandel +``` diff --git a/font/00_starmap.ttf b/font/00_starmap.ttf new file mode 100644 index 0000000..33dcf30 Binary files /dev/null and b/font/00_starmap.ttf differ diff --git a/font/noto_mono_regular.ttf b/font/noto_mono_regular.ttf new file mode 100644 index 0000000..3560a3a Binary files /dev/null and b/font/noto_mono_regular.ttf differ diff --git a/inc/mandel.h b/inc/mandel.h index 1496aa0..80cb5f4 100644 --- a/inc/mandel.h +++ b/inc/mandel.h @@ -6,13 +6,16 @@ # include # include # include +# include -#define SDL_CALL(x) do { \ +# define SDL_CALL(x) do { \ SDL_ClearError(); \ x; \ error_check_sdl(#x, __FILE__, __LINE__); \ } while (0) +# define TTF_CALL SDL_CALL + enum { KEY_UP = 0, @@ -56,8 +59,16 @@ typedef struct SDL_Window *window; SDL_Renderer *renderer; bool running; - SDL_Texture *texture; + + TTF_Font *font; + SDL_Texture *texture_center; + SDL_Texture *texture_iterations; + SDL_Texture *texture_time; + bool info; + Color *palette; + SDL_Texture *texture; + double real_start; double real_end; double imag_start; @@ -82,4 +93,15 @@ void error_check_sdl(const char *code, const char *filename, int line_num); // color.c Color *color_palette_new(Color *palette, int iterations); +// text.c +# define TEXT_TEXTURE_UPDATE(state, texture, fmt, ...) do { \ + if (state->info) { \ + SDL_DestroyTexture(texture); \ + texture = text_texture_new(state, fmt, __VA_ARGS__); \ + } \ +} while(0) + +SDL_Texture *text_texture_new(State *state, const char *fmt, ...); +void text_render(State *state, SDL_Texture *texture, int x, int y, int w, int h); + #endif diff --git a/src/event.c b/src/event.c index 9b05b76..d4ce727 100644 --- a/src/event.c +++ b/src/event.c @@ -33,7 +33,10 @@ void event_handle(State *state) break; case SDL_KEYDOWN: - st_set_key(e.key.keysym.sym, true); + if (e.key.keysym.sym == SDLK_i) + state->info = !state->info; + else + st_set_key(e.key.keysym.sym, true); break; case SDL_KEYUP: @@ -112,27 +115,51 @@ static void st_set_key(SDL_Keycode sym, bool value) } } -#define MANDEL_ITERATIONS_DELTA 2 +#define MANDEL_ITERATIONS_DELTA 1 + +#define EVENT_TEXTURE_CENTER_UPDATE(state) \ + TEXT_TEXTURE_UPDATE(state, state->texture_center, "center: %.3ei + %.3e", \ + state->imag_start + (state->imag_end - state->imag_start) / 2.0, \ + state->real_start + (state->real_end - state->real_start) / 2.0) + static void st_apply_keys(State *state) { if (g_key_states[KEY_INC_ITERATIONS]) + { state->iterations += MANDEL_ITERATIONS_DELTA; + state->palette = color_palette_new(state->palette, state->iterations); + TEXT_TEXTURE_UPDATE(state, state->texture_iterations, "iterations: %d", state->iterations); + } if (g_key_states[KEY_DEC_ITERATIONS]) { state->iterations -= MANDEL_ITERATIONS_DELTA; if (state->iterations <= 0) state->iterations = 1; + state->palette = color_palette_new(state->palette, state->iterations); + TEXT_TEXTURE_UPDATE(state, state->texture_iterations, "iterations: %d", state->iterations); } if (g_key_states[KEY_UP]) + { st_move_vertical(state, false); + EVENT_TEXTURE_CENTER_UPDATE(state); + } if (g_key_states[KEY_DOWN]) + { st_move_vertical(state, true); + EVENT_TEXTURE_CENTER_UPDATE(state); + } if (g_key_states[KEY_LEFT]) + { st_move_horizontal(state, false); + EVENT_TEXTURE_CENTER_UPDATE(state); + } if (g_key_states[KEY_RIGHT]) + { st_move_horizontal(state, true); + EVENT_TEXTURE_CENTER_UPDATE(state); + } if (g_key_states[KEY_ZOOM_IN]) st_zoom(state, true); diff --git a/src/state.c b/src/state.c index 395d590..c1bdacb 100644 --- a/src/state.c +++ b/src/state.c @@ -1,9 +1,13 @@ #include "config.h" #include "mandel.h" +#define MANDEL_FONT_PATH "font/00_starmap.ttf" +#define MANDEL_FONT_SIZE 12 + bool state_init(State *state) { SDL_CALL(SDL_Init(SDL_INIT_VIDEO)); + TTF_CALL(TTF_Init()); SDL_CALL(state->window = SDL_CreateWindow( MANDEL_WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, @@ -20,15 +24,20 @@ bool state_init(State *state) MANDEL_WINDOW_WIDTH, MANDEL_WINDOW_HEIGHT )); + TTF_CALL(state->font = TTF_OpenFont(MANDEL_FONT_PATH, MANDEL_FONT_SIZE)); + state->iterations = MANDEL_ITERATIONS; + state->texture_iterations = text_texture_new(state, "iterations: %d", state->iterations); + state->texture_time = text_texture_new(state, "time: 0ms"); + state->texture_center = text_texture_new(state, "center: 0i + 0"); state->palette = color_palette_new(NULL, MANDEL_ITERATIONS); if (state->palette == NULL) return false; - state->iterations = MANDEL_ITERATIONS; state->real_start = -2.0; state->real_end = 2.0; state->imag_start = -2.0; state->imag_end = 2.0; state->running = true; + state->info = false; return true; } @@ -62,8 +71,7 @@ void state_run(State *state) for (int j = 0; j < width; j++) { int n = mandelbrot(real, imag, state->iterations); - Color c = state->palette[n]; - ((Color*)pixels)[i * width + j] = c; + ((Color*)pixels)[i * width + j] = state->palette[n]; real += real_step; } imag += imag_step; @@ -71,11 +79,16 @@ void state_run(State *state) uint32_t render_end_time = SDL_GetTicks(); - printf("%ums\r", (render_end_time - render_start_time)); - fflush(stdout); - SDL_UnlockTexture(state->texture); SDL_CALL(SDL_RenderCopy(state->renderer, state->texture, NULL, NULL)); + if (state->info) + { + TEXT_TEXTURE_UPDATE(state, state->texture_time, "time: %u", render_end_time - render_start_time); + text_render(state, state->texture_center, 10, 10, 200, 12); + text_render(state, state->texture_iterations, 10, 30, 90, 12); + text_render(state, state->texture_time, 10, 50, 45, 12); + } + SDL_RenderPresent(state->renderer); SDL_Delay(3); } @@ -84,8 +97,13 @@ void state_run(State *state) void state_quit(State *state) { free(state->palette); + TTF_CloseFont(state->font); + SDL_DestroyTexture(state->texture_iterations); + SDL_DestroyTexture(state->texture_center); + SDL_DestroyTexture(state->texture_time); SDL_DestroyTexture(state->texture); SDL_DestroyRenderer(state->renderer); SDL_DestroyWindow(state->window); + TTF_Quit(); SDL_Quit(); } diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..97b3081 --- /dev/null +++ b/src/text.c @@ -0,0 +1,34 @@ +#include "mandel.h" + +#define MANDEL_TEXT_BUF_SIZE 128 + +SDL_Texture *text_texture_new(State *state, const char *fmt, ...) +{ + SDL_Texture *texture; + SDL_Surface *surface; + SDL_Color color; + char buf[MANDEL_TEXT_BUF_SIZE]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, MANDEL_TEXT_BUF_SIZE, fmt, ap); + va_end(ap); + color.r = 0; + color.g = 0; + color.b = 0; + color.a = 255; + TTF_CALL(surface = TTF_RenderText_Solid(state->font, buf, color)); + SDL_CALL(texture = SDL_CreateTextureFromSurface(state->renderer, surface)); + SDL_FreeSurface(surface); + return texture; +} + +void text_render(State *state, SDL_Texture *texture, int x, int y, int w, int h) +{ + SDL_Rect dst; + dst.x = x; + dst.y = y; + dst.w = w; + dst.h = h; + SDL_CALL(SDL_RenderCopy(state->renderer, texture, NULL, &dst)); +} -- cgit