Skip to content

alcarril/Fractol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

15 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

fract-ol

Fractal explorer for Mandelbrot and Julia sets built with MiniLibX.

42 School Project Made with C MiniLibX


๐Ÿ“– Overview

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.

๐Ÿ–ฅ๏ธ Demo

Mandelbrot

Julia

๐Ÿ› ๏ธ Core Features and technical highlights

Fractal Rendering

  • โœ… 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

Input and Interaction

  • ๐Ÿ–ฑ๏ธ 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

Color and Visuals

  • ๐ŸŽจ Gradient-based palette based on escape iterations
  • ๐ŸŒˆ Custom color treatment to highlight detail


Getting Started

๐Ÿ“‚ Project Structure

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

Project Overview:

You can view the complete project architecture and ask an AI about the code here: https://deepwiki.com/alcarril/Fractol

๐Ÿ“‹ Requirements

  • Linux with X11 (Xlib, Xext, Xfixes) and zlib.
  • cc and make.
  • MiniLibX: included in this repository.
  • Libft: included in this repository.

๐Ÿ”ง Installation

Install dependencies (Ubuntu/Debian)

sudo apt-get update
sudo apt-get install gcc make xorg libxext-dev libbsd-dev libxfixes-dev

Clone the Repository

git clone https://github.com/alcarril/Fractol.git
cd Fractol

โ–ถ๏ธ Build and run

make
./fractol Mandelbrot
./fractol Julia -0.8 0.156


Usage

๐ŸŽฎ Controls

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 parameters

Julia requires two parameters for the constant $c$:

./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.



MLX and X11 integration

๐ŸŒ What is X11 (client-server model)

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.

โšก What is MiniLibX

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.

X11 pipeline diagram

๐ŸชŸ Windows and images

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

๐Ÿ’พ Image buffering vs. direct pixel drawing

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.

๐Ÿ–๏ธ MLX drawing functions

Function Target Method
mlx_pixel_put Window Single pixel at a time
mlx_put_image_to_window Window Full image buffer blit

๐Ÿช Events detection (hooks)

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

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.

๐Ÿงฎ How do we calculate fractals?

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 $z_{n+1} = z_n^2 + c$) and repeat the process a fixed number of times. If at any step the value of $|z_n|$ exceeds an escape radius (typically $2$), we consider the point divergent.

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.

๐ŸŽจ How do we select the color?

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.

๐Ÿ”Ž What about infinite zoom?

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.

1๏ธโƒฃ Mandelbrot Set

The Mandelbrot set is defined by the iteration:

$$ z_{n+1} = z_n^2 + c, \quad z_0 = 0 $$

A point $c$ belongs to the set if the sequence does not diverge. Coloring is based on the number of iterations before escape.

Mandelbrot Demo Mandelbrot 3
Mandelbrot Demo 4 Mandelbrot

2๏ธโƒฃ Julia Set

The Julia set fixes $c$ and iterates the sequence for each pixel mapped to $z_0$:

$$ z_{n+1} = z_n^2 + c, \quad z_0 = x + iy $$

If $|z_n|$ grows beyond a chosen escape radius (commonly $2$), the point is considered divergent. The color is based on the number of iterations before escape.

Recommended $c$ values (Julia configurations)

Use these values to explore different looks. Replace the image paths with your own captures.

c = 0.0 + 0.8i
./fractol Julia 0.0 0.8
Julia Julia 1
c = -0.8 + 0.156i
./fractol Julia -0.8 0.156
Julia Dragon Julia Dragon 1 Julia Dragon 2
c = 0.37 + 0.1i
./fractol Julia 0.37 0.1
Julia Hojas Julia Hojas 2
c = 0.355 + 0.355i
./fractol Julia 0.355 0.355
Julia Tornado Julia Tornado 2 Julia Tornado 3
c = -0.54 + 0.54i
./fractol Julia -0.54 0.54
Julia Nose Julia Nose 2
c = -0.4 - 0.59i
./fractol Julia -0.4 -0.59
Julia 2 Julia 3 Julia 5
c = 0.34 - 0.05i
./fractol Julia 0.34 -0.05
Julia Julian Julia Julian 2


Features

๐Ÿ–ผ๏ธ Image scaling in the render pipeline

Fractals are rendered by mapping each screen pixel $(x, y)$ to a point in the complex plane. This mapping is a linear scaling between two spaces:

$$ x_c = x_{min} + \frac{x}{W} (x_{max} - x_{min}), \quad y_c = y_{min} + \frac{y}{H} (y_{max} - y_{min}) $$

Where $W$ and $H$ are the window dimensions, and $(x_{min}, x_{max}, y_{min}, y_{max})$ define the current viewport. Zoom and pan update the viewport bounds, which effectively rescales the complex-plane window without changing the screen resolution.

๐Ÿ” Zoom transformation

The zoom operation applies an affine transformation centered at the cursor position:

$$ p' = c + s \cdot (p - c) $$

Where $c$ is the zoom center and $s$ is the scale factor. Translation is applied by adding a displacement vector to the viewport bounds.

๐ŸŽฏ Practical effects

  • 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$.

โ“ Why scale pixels to the set?

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.



โ„น๏ธโ€‹ Resources

Mathematics

Complex numbers

Fractal

Math library

Mlx and X11



๐Ÿ‘จโ€๐Ÿ’ป Author

Alejandro Carrillo @alcarril


๐Ÿ“œ License

This project does not include a license file in the repository.

Releases

No releases published

Packages

 
 
 

Contributors