@@ 1,5 1,6 @@
CC = gcc
CFLAGS = -Wall -Wextra -Werror -g3 -I include/
+LIBFLAGS = -lm -lSDL3
SRC = src/main.c src/color.c src/math.c
OBJ = $(SRC:.c=.o)
@@ 11,7 12,7 @@ bear:
bear -- make fclean all
$(OUT): $(OBJ)
- $(CC) -o $(OUT) $(OBJ) -lm
+ $(CC) -o $(OUT) $(OBJ) $(LIBFLAGS)
clean:
rm -f $(OBJ)
@@ 1,27 1,84 @@
+#include "SDL3/SDL.h"
#include "mandelbrot.h"
+#include <SDL3/SDL_events.h>
+#include <SDL3/SDL_init.h>
+#include <SDL3/SDL_oldnames.h>
+#include <SDL3/SDL_rect.h>
+#include <SDL3/SDL_render.h>
+#include <SDL3/SDL_surface.h>
+#include <SDL3/SDL_video.h>
#include <stdio.h>
+#include <stdlib.h>
-int main() {
- int width = 800;
- int height = 600;
- int max_iter = 100;
+// TODO: GPU shadering option
+// TODO: flexible window size
+// TODO: zooming in and out
+// TODO: maybe? change colors
+
+#define WINDOW_TITLE "Mandelbrot Visualization"
+#define WINDOW_WIDTH 800
+#define WINDOW_HEIGHT 600
+
+static int points[WINDOW_WIDTH * WINDOW_HEIGHT];
+void calculate_points() {
double x_min = -2.0, x_max = 1.0;
double y_min = -1.2, y_max = 1.2;
+ int max_iter = 100;
+ for (int py = 0; py < WINDOW_HEIGHT; py++) {
+ for (int px = 0; px < WINDOW_WIDTH; px++) {
+ double cr = x_min + (x_max - x_min) * px / (WINDOW_WIDTH - 1);
+ double ci = y_min + (y_max - y_min) * py / (WINDOW_HEIGHT - 1);
+ points[py * WINDOW_WIDTH + px] = mandelbrot_iterations(cr, ci, max_iter);
+ }
+ }
+}
- // PPM header (P3 = ASCII, width, height, max color value)
- printf("P3\n%d %d\n255\n", width, height);
-
- for (int py = 0; py < height; py++) {
- for (int px = 0; px < width; px++) {
- double cr = x_min + (x_max - x_min) * px / (width - 1);
- double ci = y_min + (y_max - y_min) * py / (height - 1);
- int iter = mandelbrot_iterations(cr, ci, max_iter);
+void draw_points(SDL_Surface* surface) {
+ for (int py = 0; py < WINDOW_HEIGHT; py++) {
+ for (int px = 0; px < WINDOW_WIDTH; px++) {
int r, g, b;
- get_color(iter, max_iter, &r, &g, &b);
- printf("%d %d %d ", r, g, b);
+ get_color(points[py * WINDOW_WIDTH + px], 100, &r, &g, &b);
+ SDL_WriteSurfacePixel(surface, px, py, r, g, b, 255);
}
- printf("\n");
}
+};
+
+int main(void) {
+ if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) {
+ fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ SDL_Window* window =
+ SDL_CreateWindow(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_HIDDEN);
+ if (window == NULL) {
+ fprintf(stderr, "CreateWindowAndRenderer failed: %s\n", SDL_GetError());
+ SDL_Quit();
+ return -1;
+ }
+
+ SDL_Surface* surface = SDL_GetWindowSurface(window);
+ if (!surface) {
+ return -1;
+ }
+ SDL_Event e;
+ bool running = true;
+ SDL_UpdateWindowSurface(window);
+ SDL_ShowWindow(window);
+ while (running) {
+ while (SDL_PollEvent(&e)) {
+ if (e.type == SDL_EVENT_QUIT) {
+ running = false;
+ }
+ }
+ calculate_points();
+ draw_points(surface);
+ SDL_UpdateWindowSurface(window);
+ SDL_Delay(16);
+ }
+
+ SDL_DestroyWindow(window);
+ SDL_Quit();
return 0;
}