Created
October 4, 2023 20:56
-
-
Save davawen/19acca47250e687f51deb55f16145c67 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL2/SDL.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <assert.h> | |
#include <pthread.h> | |
typedef struct { | |
double real; | |
double imag; | |
} complex_t; | |
uint16_t max_iter = 255; | |
uint16_t mandelbrot(complex_t c) { | |
complex_t z = { 0 }; | |
for (uint16_t iterations = 0; iterations < max_iter; iterations++) { | |
if (z.real >= 2 || z.imag >= 2) return iterations; | |
// (a + bi)^2 | |
// a^2 + 2abi - b^2 | |
z = (complex_t) { | |
.real = z.real*z.real - z.imag*z.imag, | |
.imag = 2*z.real*z.imag | |
}; | |
z.real += c.real; | |
z.imag += c.imag; | |
} | |
return max_iter; | |
} | |
typedef struct { | |
double x, y; | |
double zoom; | |
} Camera; | |
typedef struct { | |
SDL_Renderer *renderer; | |
const Camera *camera; | |
int w; | |
int h; | |
unsigned int id; | |
unsigned int num; | |
uint16_t *buf; | |
} ThreadData; | |
void *render(void *data) { | |
ThreadData d = *(ThreadData *)data; | |
const Camera *cam = d.camera; | |
int w = d.w, h = d.h; | |
for (int y = d.id; y < h; y += d.num) { | |
for (int x = 0; x < w; x++) { | |
complex_t c = { | |
.real = ((double)x / w - 0.5) * cam->zoom + cam->x, | |
.imag = ((double)y / w - ((double)h/w)/2.0) * cam->zoom + cam->y | |
}; | |
d.buf[y*w + x] = mandelbrot(c); | |
} | |
} | |
return NULL; | |
} | |
int main() { | |
SDL_Window *window; | |
SDL_Renderer *renderer; | |
assert(SDL_Init(SDL_INIT_VIDEO) == 0); | |
SDL_CreateWindowAndRenderer(640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE, &window, &renderer); | |
assert(window != NULL); | |
assert(renderer != NULL); | |
SDL_RenderClear(renderer); | |
Camera camera = { | |
.x = -0.5, .y = 0.0, | |
.zoom = 2.5 | |
}; | |
struct { | |
uint16_t *data; | |
uint32_t len; | |
} buf = { NULL, 0 }; | |
bool holding_shift = false; | |
bool window_open = true; | |
bool rerender = true; | |
while (window_open) { | |
int w, h; | |
SDL_GetWindowSize(window, &w, &h); | |
SDL_Event event; | |
while (SDL_PollEvent(&event)) { | |
switch (event.type) { | |
case SDL_QUIT: | |
window_open = false; | |
break; | |
case SDL_KEYDOWN: | |
if (event.key.keysym.sym == SDLK_LSHIFT) holding_shift = true; | |
break; | |
case SDL_KEYUP: | |
if (event.key.keysym.sym == SDLK_LSHIFT) holding_shift = false; | |
break; | |
case SDL_MOUSEWHEEL: | |
if (holding_shift) { | |
if (event.wheel.y < 0 && max_iter > 1 || event.wheel.y > 0 && max_iter < 1000) { | |
max_iter += event.wheel.y; | |
printf("%ui\n", max_iter); | |
rerender = true; | |
} | |
} else { | |
double delta = (double)event.wheel.y / 10.0; | |
camera.x += camera.zoom*delta*((double)event.wheel.mouseX / w - 0.5); | |
camera.y += camera.zoom*delta*((double)event.wheel.mouseY / w - ((double)h/w/2.0)); | |
camera.zoom *= 1.0 - delta; | |
rerender = true; | |
} | |
break; | |
case SDL_WINDOWEVENT: | |
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) | |
rerender = true; | |
break; | |
} | |
} | |
if (rerender) { | |
uint32_t len = w*h*sizeof(uint16_t); | |
if (buf.len < len) { | |
buf.data = malloc(len); | |
buf.len = len; | |
} | |
pthread_t t[6]; | |
ThreadData d[6]; | |
for (int i = 0; i < 6; i++) { | |
d[i] = (ThreadData) { | |
renderer, &camera, w, h, i, 6, buf.data | |
}; | |
pthread_create(&t[i], NULL, render, &d[i]); | |
} | |
for (int i = 0; i < 6; i++) { | |
pthread_join(t[i], NULL); | |
} | |
for (int y = 0; y < h; y++) { | |
for (int x = 0; x < w; x++) { | |
uint16_t i = buf.data[y*w + x]; | |
if (i == max_iter) SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | |
else SDL_SetRenderDrawColor(renderer, i*255 / max_iter, i*128/max_iter, 0, 255); | |
SDL_RenderDrawPoint(renderer, x, y); | |
} | |
} | |
rerender = false; | |
SDL_RenderPresent(renderer); | |
} | |
SDL_Delay(1000 / 60); | |
} | |
free(buf.data); | |
SDL_Quit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment