aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--README.md28
-rw-r--r--font/00_starmap.ttfbin0 -> 25056 bytes
-rw-r--r--font/noto_mono_regular.ttfbin0 -> 107848 bytes
-rw-r--r--inc/mandel.h26
-rw-r--r--src/event.c31
-rw-r--r--src/state.c30
-rw-r--r--src/text.c34
8 files changed, 121 insertions, 33 deletions
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 <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
+```
+make all
+./mandel
+```
diff --git a/font/00_starmap.ttf b/font/00_starmap.ttf
new file mode 100644
index 0000000..33dcf30
--- /dev/null
+++ b/font/00_starmap.ttf
Binary files differ
diff --git a/font/noto_mono_regular.ttf b/font/noto_mono_regular.ttf
new file mode 100644
index 0000000..3560a3a
--- /dev/null
+++ b/font/noto_mono_regular.ttf
Binary files 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 <math.h>
# include <immintrin.h>
# include <SDL2/SDL.h>
+# include <SDL2/SDL_ttf.h>
-#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));
+}