Skip to content

modimihir07/BlackHole-Simulation_Using_Rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🕳️ Gargantua — Black Hole Simulator

A ray tracer that renders a spinning black hole with an accretion disk, gravitational lensing, Doppler beaming, and a star field background. Written in Rust. Inspired by the black hole from Interstellar.

Rendered black hole

This started as a weekend project to see if I could get a physically plausible black hole render without reaching for a GPU. Turns out, Rust + Rayon make CPU ray tracing surprisingly fast.


🔭 What it does

The program fires ~2 million rays from a virtual camera, and for each one, numerically integrates the photon's path through the curved spacetime of a Kerr (spinning) black hole. Depending on where the ray ends up, you get one of three outcomes:

  • Captured — the photon crosses the event horizon. Pixel goes black.
  • 🟠 Disk hit — the photon crosses the equatorial plane within the accretion disk's bounds. It gets colored based on blackbody temperature and Doppler shift.
  • Escaped — the photon flies off to infinity. It gets matched against a procedural star field.

After all rays are traced, a simple bloom pass adds a soft glow around bright pixels for that cinematic look.


🌌 How the physics works

The gravitational acceleration on a photon at position p with velocity v is:

a = -(M / r^3) * p * (1 + 3 * h^2 / r^2)
  • M is the black hole mass
  • r is the distance from the singularity
  • h^2 = |p x v|^2 is the squared angular momentum of the photon

That extra (1 + 3h^2/r^2) term is what makes it general-relativistic rather than Newtonian — it's responsible for producing the photon sphere at r = 3M, which is where light can actually orbit the black hole. Without it, you'd just get boring straight-line deflection.

Integration is done with RK4 (4th-order Runge-Kutta) and adaptive time-stepping. Steps get very small near the horizon to maintain accuracy, and larger out in flat space where precision matters less.

🎨 Accretion disk coloring

The disk isn't just a flat color. Each point on the disk has a temperature based on its radius — hotter toward the inner edge (~11,000 K, bluish-white) and cooler at the outer edge (~1,800 K, deep red). These temperatures get converted to RGB using a blackbody approximation.

On top of that, Keplerian orbital motion means one side of the disk is moving toward you (blue-shifted, brighter) and the other side is moving away (red-shifted, dimmer). The brightness boost follows a D^3 law, where D is the Doppler factor. This asymmetry is one of the most visually striking features of a real black hole.


🚀 Running it

You need Rust installed — grab it from rustup.rs if you don't have it.

git clone https://github.com/your-username/blackhole-sim.git
cd blackhole-sim
cargo run --release

Use --release. Seriously. The release profile has opt-level = 3 and LTO enabled, so it's dramatically faster than a debug build. The render takes a minute or two in release mode; in debug mode, you'll be waiting a while.

Output goes to blackhole.png in the project root. 🖼️


⚙️ Tweaking the parameters

Everything is configured through constants at the top of src/main.rs. No config files, no CLI args — just edit the values and rebuild. Here's what you can play with:

Black hole

Constant Default What it controls
BH_MASS 1.5 Shadow size. Bigger mass = bigger shadow
BH_SPIN 0.97 Spin. 0 = non-spinning (Schwarzschild), 1 = maximum spin

Camera

Constant Default What it controls
CAM_R 35.0 How far the camera is from the black hole
CAM_INCL 80 degrees Viewing angle. 90 = edge-on, 0 = looking down the spin axis
CAM_FOV 28 degrees Field of view

Disk and rendering

Constant Default What it controls
DISK_INNER 3.5 Inner edge of the accretion disk
DISK_OUTER 16.0 Outer edge of the accretion disk
NUM_STARS 5000 Background stars
MAX_STEPS 4000 Max integration steps per ray (increase if rays aren't converging)
WIDTH / HEIGHT 1920 x 1080 Output resolution

🧪 Some fun presets to try

  • Schwarzschild: Set BH_SPIN = 0.0 — no spin, perfectly symmetric shadow
  • Polar view: Set CAM_INCL = 15.0 — looking almost straight down. You'll see the disk as a near-perfect ring
  • Edge-on: Set CAM_INCL = 89.0 — extreme equatorial view, lots of warped lensing arcs
  • Higher res: Bump WIDTH / HEIGHT up if you want a wallpaper. Render time scales linearly

🏗️ Project structure

The whole thing is a single file (src/main.rs). It's about 300 lines. Here's the rough layout:

V3              — basic 3D vector type (dot, cross, normalize, etc.)
accel()         — the GR acceleration formula
step()          — one RK4 timestep
make_ray()      — maps a pixel coordinate to a ray direction
trace()         — integrates a ray until it hits something or escapes
disk_rgb()      — temperature + Doppler -> RGB for disk hits
bb_rgb()        — converts a Kelvin temperature to an RGB color
gen_stars()     — generates a random star field (seeded, so it's deterministic)
sky_rgb()       — looks up the nearest star for escaped rays
bloom()         — post-processing glow
main()          — ties everything together

📦 Dependencies

Just three crates, nothing exotic:

  • image (0.25) — for writing the output PNG
  • rayon (1.10) — for parallelizing the ray tracing across all CPU cores
  • rand (0.8) — for generating the star field (uses a fixed seed, so renders are reproducible)

📝 Notes

  • The star field uses a fixed RNG seed (42), so you'll get the same stars every time. Change the seed in gen_stars() if you want a different sky.
  • The event horizon radius is computed as r+ = M + sqrt(M^2 - a^2) where a = spin * M. For the default spin of 0.97, the horizon is quite small.
  • Bloom radius is 3 pixels with an exponential falloff. It's subtle but makes the hot inner disk glow nicely.

License

MIT — do whatever you want with it. 🤙

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages