summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2023-09-03 18:45:39 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2023-09-03 18:45:39 +0100
commit913e540b9266dc0d4ba3dbd57c4fe0abdf138c4e (patch)
tree1aea59cb1f54faa6ba74e91af0830c2e942a78bb
parentaab3db7f321067b8ff14d589119936d3cbbfc2b0 (diff)
downloadoreobrot-913e540b9266dc0d4ba3dbd57c4fe0abdf138c4e.tar.gz
oreobrot-913e540b9266dc0d4ba3dbd57c4fe0abdf138c4e.tar.bz2
oreobrot-913e540b9266dc0d4ba3dbd57c4fe0abdf138c4e.zip
Tons of changes: can now simulate the mandelbrot for n iterations
Essentially using a naive threaded solution with a naive escape routine for choosing whether a given location is actually in the Mandelbrot set. I think the colouring solution is quite unique: I use a scaled quadratic function which ensures maximum colouring is given to those with medium number of iterations. I'll try a linear ratio next. Currently we start properly lagging at ~2^20 iterations, which is why I'm looking for a better way to draw and compute escapes.
-rw-r--r--main.c156
1 files changed, 152 insertions, 4 deletions
diff --git a/main.c b/main.c
index f9388d5..376b1f8 100644
--- a/main.c
+++ b/main.c
@@ -4,26 +4,174 @@
* Description: Entrypoint of program
*/
+#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+
+#include <pthread.h>
+#include <unistd.h>
#include <raylib.h>
#include <raymath.h>
-#define WIDTH 512
-#define HEIGHT 512
+#define WIDTH 1024
+#define HEIGHT 1024
+#define MAX_THREADS 4
+uint64_t MAX_ITER = 1 << 2;
+
+Color cells[WIDTH * HEIGHT];
+pthread_t threads[MAX_THREADS];
+pthread_mutex_t mutex;
+
+#define SQUARE(a) (a * a)
+
+Color iter_to_colour(size_t iterations)
+{
+ if (iterations == MAX_ITER)
+ return BLACK;
+
+ // quadratic ratio
+ float ratio = Remap(iterations * (MAX_ITER - iterations), 0,
+ SQUARE(MAX_ITER) / 4, 0, 1);
+
+ return (Color){255 * SQUARE(ratio), 10, 255 * SQUARE(1 - ratio), 255};
+}
+struct ThreadArg
+{
+ size_t x_0, x_t;
+ size_t y_0, y_t;
+ bool done;
+};
+
+void *generate_colours(void *state)
+{
+ struct ThreadArg *ptr = (struct ThreadArg *)state;
+ ptr->done = false;
+ for (size_t i = ptr->x_0; i < ptr->x_t; ++i)
+ for (size_t j = ptr->y_0; j < ptr->y_t; ++j)
+ {
+ Vector2 init = {Remap(i, 0, WIDTH, -1.5, 0.5),
+ Remap(j, 0, HEIGHT, -1, 1)};
+ Vector2 update = {0};
+ size_t iterations;
+ for (iterations = 0;
+ iterations < MAX_ITER && Vector2LengthSqr(update) <= 4; ++iterations)
+ {
+ double new_x = SQUARE(update.x) - SQUARE(update.y) + init.x;
+ update.y = (2 * update.x * update.y) + init.y;
+ update.x = new_x;
+ }
+ Color c = iter_to_colour(iterations);
+ cells[(i * WIDTH) + j] = c;
+ }
+ ptr->done = true;
+ return NULL;
+}
+
+void threads_start_render(struct ThreadArg *args)
+{
+ for (size_t i = 0; i < MAX_THREADS; ++i)
+ pthread_create(&threads[i], NULL, &generate_colours, &args[i]);
+}
+
+bool threads_done(struct ThreadArg *args)
+{
+ for (size_t i = 0; i < MAX_THREADS; ++i)
+ if (!args[i].done)
+ return false;
+ return true;
+}
+
+void threads_cancel_render(void)
+{
+ for (size_t i = 0; i < MAX_THREADS; ++i)
+ pthread_join(threads[i], NULL);
+}
+
+#define ZOOM_INC 0.3f
+#define MOVE_INC WIDTH / 50
int main(void)
{
InitWindow(WIDTH, HEIGHT, "Mandelbrot simulation");
- for (size_t ticks = 0; !WindowShouldClose(); ++ticks)
+ Camera2D camera = {0};
+ camera.zoom = 1.0f;
+
+ Image img = GenImageColor(WIDTH, HEIGHT, BLACK);
+ ImageFormat(&img, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
+ /* Texture2D texture = LoadTextureFromImage(img); */
+ UnloadImage(img);
+
+ SetTargetFPS(60);
+
+ pthread_mutex_init(&mutex, NULL);
+ struct ThreadArg args[] = {{0, WIDTH / 2, 0, HEIGHT, false},
+ {WIDTH / 2, WIDTH, 0, HEIGHT / 4, false},
+ {WIDTH / 2, WIDTH, HEIGHT / 4, HEIGHT / 2, false},
+ {WIDTH / 2, WIDTH, HEIGHT / 2, HEIGHT, false}};
+ threads_start_render(args);
+
+ const size_t delta = 1;
+
+ for (size_t prev = 0, ticks = 0; !WindowShouldClose(); ++ticks)
{
+ if (IsKeyPressed(KEY_UP) || IsKeyDown(KEY_UP))
+ camera.target.y -= MOVE_INC;
+ else if (IsKeyPressed(KEY_DOWN) || IsKeyDown(KEY_DOWN))
+ camera.target.y += MOVE_INC;
+ else if (IsKeyPressed(KEY_RIGHT) || IsKeyDown(KEY_RIGHT))
+ camera.target.x += MOVE_INC;
+ else if (IsKeyPressed(KEY_LEFT) || IsKeyDown(KEY_LEFT))
+ camera.target.x -= MOVE_INC;
+ else if (IsKeyPressed(KEY_N) || IsKeyDown(KEY_N))
+ {
+ camera.zoom += ZOOM_INC;
+ if (camera.zoom > 3.0f)
+ camera.zoom = 3.0f;
+ }
+ else if (IsKeyPressed(KEY_M) || IsKeyDown(KEY_M))
+ {
+ camera.zoom -= ZOOM_INC;
+ if (camera.zoom < 0.1f)
+ camera.zoom = 0.1f;
+ }
+ else if (IsKeyPressed(KEY_SPACE))
+ {
+ while (!threads_done(args))
+ continue;
+ memset(cells, 0, WIDTH * HEIGHT);
+ MAX_ITER *= 2;
+ threads_cancel_render();
+ threads_start_render(args);
+ }
+
+ if (ticks - prev > delta)
+ {
+ prev = ticks;
+ /* UpdateTexture(texture, cells); */
+ }
+
BeginDrawing();
+ BeginMode2D(camera);
ClearBackground(BLACK);
- DrawText("Hello, world!", 100, 100, 50, RAYWHITE);
+ char iters[128];
+ sprintf(iters, "iterations=%lu", MAX_ITER);
+ /* DrawTexture(texture, 1024, 1024, BLUE); */
+ for (size_t i = 0; i < WIDTH; ++i)
+ {
+ for (size_t j = 0; j < HEIGHT; ++j)
+ {
+ DrawPixel(i, j, cells[(i * WIDTH) + j]);
+ }
+ }
+ DrawText(iters, 200, 200, 50, RAYWHITE);
+ EndMode2D();
EndDrawing();
}
+ threads_cancel_render();
+ /* UnloadTexture(texture); */
CloseWindow();
return 0;
}