Drawing a Sierpinski Triangle in Rust with macroquad


This is a compact Rust program that opens a window and draws a Sierpinski triangle recursively. It uses macroquad, a simple Rust game library with built-in windowing and 2D drawing. The crate docs show the #[macroquad::main] entry pattern along with frame-by-frame rendering driven by next_frame().await, which is all we need to put pixels on screen and respond to keyboard input.

The idea is small but expressive: each recursion step splits the current triangle into three corner triangles using the midpoints of its edges and omits the center triangle — the defining construction of the Sierpinski gasket. Because the program redraws every frame, changing the recursion depth with the arrow keys immediately updates the visualization.

Code

Add this to src/main.rs:

use macroquad::prelude::*;

fn draw_filled_triangle(a: Vec2, b: Vec2, c: Vec2, color: Color) {
    draw_triangle(a, b, c, color);
}

fn sierpinski(a: Vec2, b: Vec2, c: Vec2, depth: u32, color: Color) {
    if depth == 0 {
        draw_filled_triangle(a, b, c, color);
        return;
    }

    let ab = (a + b) * 0.5;
    let bc = (b + c) * 0.5;
    let ca = (c + a) * 0.5;

    sierpinski(a, ab, ca, depth - 1, color);
    sierpinski(ab, b, bc, depth - 1, color);
    sierpinski(ca, bc, c, depth - 1, color);
}

#[macroquad::main("Sierpinski Triangle")]
async fn main() {
    let mut depth: u32 = 7;

    loop {
        if is_key_pressed(KeyCode::Up) {
            depth = (depth + 1).min(10);
        }
        if is_key_pressed(KeyCode::Down) {
            depth = depth.saturating_sub(1);
        }

        clear_background(BLACK);

        let w = screen_width();
        let h = screen_height();
        let margin = 40.0;

        let a = vec2(w / 2.0, margin);
        let b = vec2(margin, h - margin);
        let c = vec2(w - margin, h - margin);

        sierpinski(a, b, c, depth, WHITE);

        draw_text(
            &format!("Depth: {}  (Up/Down to change)", depth),
            20.0,
            30.0,
            30.0,
            GREEN,
        );

        next_frame().await;
    }
}
Cargo.toml

Add macroquad as a dependency; the crate docs and the project site both show adding it under [dependencies] and running with cargo run.

[package]
name = "sierpinski-triangle"
version = "0.1.0"
edition = "2021"

[dependencies]
macroquad = "0.4"
Repo layout

A good minimal structure matches Cargo’s default binary-package layout, where Cargo.toml defines the package and dependencies and src/main.rs is the executable entry point. If you later want multiple demos, Cargo can also build extra binaries from src/bin/*.rs.

sierpinski-triangle/
├── Cargo.toml
├── Cargo.lock
├── .gitignore
├── README.md
└── src/
    └── main.rs
Create the repo

From a terminal, create the project with Cargo, then move into it. cargo new <name> --bin creates a new directory and initializes a binary crate, while cargo init does the same inside an existing directory.

cargo new sierpinski-triangle --bin
cd sierpinski-triangle

Then replace the generated src/main.rs with the Sierpinski code above and add macroquad = "0.4" under [dependencies] in Cargo.toml, since Cargo uses that manifest file to resolve and build dependencies.

Run

For normal development, run:

cargo run

Cargo will compile the project if needed and then run the executable; debug builds are placed under target/debug/. For a faster optimized build — useful for smoother rendering at higher depths — use cargo run --release or cargo build --release, which places the optimized binary under target/release/. macroquad supports desktop platforms and HTML5, so this same visualization can later be compiled for the browser as well.

How it works

Each recursion step splits the current triangle into three corner triangles using the midpoints of its edges, and it omits the center triangle — the defining construction of the Sierpinski triangle. The program redraws every frame, so changing the recursion depth with the Up / Down arrow keys immediately updates the visualization. A quick checklist for the README:

  • Install Rust and Cargo.
  • Clone the repo.
  • Run cargo run.
  • Use the Up / Down arrow keys to change recursion depth.
  • Use cargo run --release for smoother rendering at higher depths.