fract-ol is a real-time fractal explorer that renders Mandelbrot and Julia sets using iterative complex-number mathematics and the MiniLibX (MLX) API for windowing and pixel drawing. The project focuses on interactive rendering, smooth zoom, and precise parameter control, showcasing the relationship between math and visual complexity.
- โ Mandelbrot and Julia sets with accurate escape-time coloring
- โ Configurable iteration limits for detail vs performance
- โ Smooth zoom with mouse wheel and high precision mapping
- โ Panning to explore different regions
- ๐ฑ๏ธ Mouse zoom centered at cursor position
- ๐จ Iteration control with
+and-keys for dynamic detail adjustment - ๐ฏ Keyboard movement for precise navigation
- ๐๏ธ Julia parameter control via CLI arguments
- ๐จ Gradient-based palette based on escape iterations
- ๐ Custom color treatment to highlight detail
Fractol/
โโโ libs/ # Libraries (libft propia, minilibx API)
โโโ docs/ # Documentation and images
โโโ src/ # Project sources
โ โโโ fractol.h # Main structs, constants, prototypes
โ โโโ main.c # Entry point and argument parsing
โ โโโ create_cgi_env.c # Fractal selection and MLX setup
โ โโโ events.c # Keyboard and mouse handlers
โ โโโ render.c # Pixel rendering and iteration loops
โ โโโ set_definition.c # Mandelbrot/Julia definitions
โ โโโ color_treatment.c # Color palettes and iteration coloring
โ โโโ math_utils.c # Math helpers
โ โโโ utils.c # Utilities and parsing
โโโ Makefile # Build rules
You can view the complete project architecture and ask an AI about the code here: https://deepwiki.com/alcarril/Fractol
- Linux with X11 (Xlib, Xext, Xfixes) and zlib.
ccandmake.- MiniLibX: included in this repository.
- Libft: included in this repository.
sudo apt-get update
sudo apt-get install gcc make xorg libxext-dev libbsd-dev libxfixes-devgit clone https://github.com/alcarril/Fractol.git
cd Fractolmake./fractol Mandelbrot./fractol Julia -0.8 0.156| Category | Key | Action |
|---|---|---|
| Navigation | Arrow keys | Fine pan adjustment |
| Zoom | Mouse wheel | Zoom in/out |
| Color | + / - |
Increase/decrease color iteration count per pixel |
| Exit | ESC |
Quit program |
Note: If the window is blank, try lowering the iteration count.
Julia requires two parameters for the constant
./fractol Julia <real> <imag>
Example:
./fractol Julia -0.8 0.156
Note: For stable and detailed Julia sets, keep parameters roughly within
$[-2, 2]$ for both real and imaginary parts.
X11 is a client-server graphics system. The X server owns the display, input devices, and the window tree. Applications are X clients that request windows, draw into buffers, and receive input events. In Linux/UNIX, the X11 server acts as a graphics sub-layer that manages communication between graphics hardware, the OS, and client processes, providing window creation, input event handling (keyboard and mouse), and basic screen rendering.
MiniLibX is a graphics API built on top of Xlib, the client-side library used by X11 clients to talk to the X server. In this context, our program is an X11 client, and MiniLibX abstracts the low-level Xlib API so we can manipulate windows, image buffers, and events without dealing directly with Xlib complexity.
In X11, a window is a server-side object. It is a rectangular region with an event queue and a drawable surface, but it does not render by itself. The client must draw and redraw when the server reports exposure events. X11 offers two main image concepts:
| Concept | Storage | Characteristics |
|---|---|---|
| Image (XImage) | Client memory | Pixel-accessible, slower for large transfers |
| Pixmap | Server memory | Optimized for fast blits to the window |
Direct pixel drawing sends each pixel request through the client-server pipeline, creating significant overhead when rendering thousands of pixels per frame.
Buffering with an off-screen image is more efficient: pixels are written to client-side memory, then a single blit operation transfers the completed frame to the X server. This approach minimizes network round trips and keeps computation local to the client.
Note: Fractol renders into an off-screen image buffer each frame and then pushes it to the window for flicker-free output.
| Function | Target | Method |
|---|---|---|
mlx_pixel_put |
Window | Single pixel at a time |
mlx_put_image_to_window |
Window | Full image buffer blit |
Input travels from hardware to drivers, then to the kernel, into the X server (Xorg), and finally to the client through Xlib. MiniLibX exposes this event flow as hooks, so we attach callbacks to specific event types:
| Hook | Purpose |
|---|---|
mlx_hook |
Registers generic X11 events on a window (press, release, close, expose) |
mlx_key_hook |
Provides simplified keyboard event handlers |
mlx_mouse_hook |
Provides simplified mouse event handlers |
mlx_loop_hook |
Runs a function every frame, ideal for continuous rendering |
In practice, input events update the viewport parameters, the render loop redraws the fractal into the image buffer, and mlx_put_image_to_window presents the frame.
Fractals are geometric shapes built from simple rules repeated at many scales. Their defining principles are self-similarity (patterns that look alike when zoomed), iteration (repeated mathematical steps), and sensitivity to initial conditions, which produces rich detail from compact formulas. Sets like Mandelbrot and Julia come from iterating complex-number functions on the complex plane, classifying each point by whether the sequence stays bounded or escapes.
These patterns are not just mathematical curiosities: fractal-like structures appear in nature, such as coastlines, mountain ranges, clouds, river networks, snowflakes, ferns, and even branching in trees and lightning. This project visualizes that same idea of repeating structure and infinite detail through interactive zooming.
For each pixel on the screen, we convert it to a point on the complex plane. We apply an iterative formula to that point (for example
The color of each pixel is based on how many iterations it takes to escape. If it escapes quickly, it is painted with a different color than if it takes longer or doesn't escape within the limit. This is why the maximum iteration count affects detail and palette: with + and - you can increase or decrease those iterations to see more detail or gain performance.
To colorize, you can use a color palette and scale it to the number of iterations used to decide whether the point escapes or not. Another option is to apply a mathematical gradient, modifying a base color based on the number of operations before escape. In this project, I chose to use the palette approach.
These sets are described as having infinite depth because they are perfectly imperfect: if the perfect path between two points is a straight line, the less perfect one can have infinite detail. That's why you can zoom frame after frame and keep finding new structures. In practice, the only limits are resolution, precision, and your computer's performance.
The Mandelbrot set is defined by the iteration:
A point
![]() |
![]() |
![]() |
![]() |
The Julia set fixes
If
Use these values to explore different looks. Replace the image paths with your own captures.
./fractol Julia 0.0 0.8
![]() |
![]() |
./fractol Julia -0.8 0.156
![]() |
![]() |
![]() |
./fractol Julia 0.37 0.1
![]() |
![]() |
./fractol Julia 0.355 0.355
![]() |
![]() |
![]() |
./fractol Julia -0.54 0.54
![]() |
![]() |
./fractol Julia -0.4 -0.59
![]() |
![]() |
![]() |
./fractol Julia 0.34 -0.05
![]() |
![]() |
Fractals are rendered by mapping each screen pixel
Where
The zoom operation applies an affine transformation centered at the cursor position:
Where
- Zoom in : shrink the viewport range around the cursor.
- Zoom out : expand the viewport range around the cursor.
-
Pan : translate the viewport range in
$x$ and$y$ .
For continuous sets like Mandelbrot and Julia, we iterate every pixel and map it to a complex point. This pixel-to-set approach avoids holes and aliasing that appear when projecting sparse sets onto discrete screens. It guarantees full coverage and consistent coloring across the image.
Note: ๐ More: My article on Notion.
- https://www.youtube.com/watch?v=LqyBrrgmIro&ab_channel=Derivando
- https://www.youtube.com/watch?v=hWbwBGPLvk4
- https://www.youtube.com/watch?v=Wea_1L-C9Xo
- https://www.youtube.com/watch?v=Tt-jjxjTHTQ
- https://www.youtube.com/watch?v=EOvLhZPevm0&t=16s
- https://www.youtube.com/watch?v=gB9n2gHsHN4
- https://complex-analysis.com/contenido/conjunto_de_mandelbrot.html
- https://www.geogebra.org/m/shfghkn7
- https://en.wikipedia.org/wiki/Mandelbrot_set
- https://en.wikipedia.org/wiki/Julia_set
Alejandro Carrillo @alcarril
This project does not include a license file in the repository.





















