Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Geodesic Flow -- Live Desktop Wallpaper
A real-time animated desktop wallpaper for Windows that renders families of geodesics flowing across parameterized surfaces. Geodesics are integrated with a fourth-order Runge-Kutta (RK4) scheme using analytically computed Christoffel symbols. The window sits below all application windows via a Win32 WM_WINDOWPOSCHANGING hook, leaving desktop icons fully accessible.
Built with Rust, wgpu (DirectX 12 / Vulkan / Metal), and the windows crate for Win32 integration.
Download
Head to the Releases page and download
geodesic-wallpaper-windows.zip. Extract it alongside config.toml and
run geodesic-wallpaper.exe. No installer required.
Requirements: Windows 10 or 11, any GPU with DirectX 12 or Vulkan support.
Architecture
| Module | File | Responsibility |
|---|---|---|
config |
src/config.rs |
Load and hot-reload config.toml; parse CSS hex colours |
error |
src/error.rs |
Typed error enum covering all subsystems |
surface |
src/surface/ |
Surface trait + Torus, Sphere, Saddle implementations |
geodesic |
src/geodesic.rs |
RK4 integrator for the geodesic ODE using Christoffel symbols |
trail |
src/trail.rs |
Fixed-capacity ring buffer with quadratic alpha fade |
renderer |
src/renderer/ |
wgpu render pipelines (surface wireframe + trail lines) |
renderer::camera |
src/renderer/camera.rs |
Orbiting perspective camera |
wallpaper |
src/wallpaper.rs |
Win32 borderless window pinned below all app windows |
main |
src/main.rs |
Application entry point, message loop, hot-reload watcher |
config.toml
|
v
+--------+ hot-reload +------------------+
| Config | -----------------> | SharedConfig |
+--------+ (notify watcher) | Arc<RwLock<...>> |
+------------------+
|
v
+-----------------------------+
| GeodesicEngine |
| - Surface trait |
| (Torus / Sphere / Saddle) |
| - Geodesic: RK4 integrator |
| - Christoffel symbols |
+-----------------------------+
|
v
+-----------------------------+
| TrailRenderer |
| - TrailBuffer (ring buffer) |
| - quadratic alpha fade |
+-----------------------------+
|
v
+-----------------+
| wgpu pipelines |
| (surface mesh + |
| trail lines) |
+-----------------+
|
v
+-------------------------------+
| Win32 WorkerW window |
| (HWND_BOTTOM, WS_POPUP, |
| WM_WINDOWPOSCHANGING locked) |
+-------------------------------+
Building from source
Requirements: Rust stable (1.75 or later), Windows 10 or 11, a GPU with DirectX 12, Vulkan, or Metal support.
git clone https://github.com/Mattbusel/geodesic-wallpaper.git
cd geodesic-wallpaper
cargo build --release
.\target\release\geodesic-wallpaper.exe
Place config.toml in the same directory as the executable. The application
reloads the file automatically whenever it changes on disk. Press Ctrl+C in the
terminal or close the process to stop.
To run tests (no GPU required):
cargo test --lib
Configuration reference
All fields are optional. Missing fields revert to the defaults listed below.
| Field | Type | Default | Description |
|---|---|---|---|
surface |
string | "torus" |
Surface to render: "torus", "sphere", or "saddle" |
num_geodesics |
integer | 30 |
Number of simultaneous geodesic curves |
trail_length |
integer | 300 |
Frames a trail persists before respawning |
rotation_speed |
float | 0.001047 |
Camera orbit speed in radians per second |
color_palette |
string[] | 5 entries | CSS hex colour strings cycled across geodesics |
torus_R |
float | 2.0 |
Torus major radius (centre to tube centre) |
torus_r |
float | 0.7 |
Torus minor radius (tube radius) |
time_step |
float | 0.016 |
RK4 integration timestep in seconds per frame |
# Surface to render.
# Accepted values: "torus", "sphere", "saddle".
# Any other value falls back to "torus".
# Default: "torus"
= "torus"
# Number of simultaneous geodesic curves.
# Default: 30
= 30
# Number of frames a trail persists before being respawned.
# Default: 300
= 300
# Camera orbit angular speed in radians per second.
# 0.001047 is approximately one full revolution every 100 minutes.
# Default: 0.001047
= 0.001047
# Trail color palette as CSS hex strings (with or without leading '#').
# Geodesics cycle through the list in order.
# Default: five entries from blue to gold to pink.
= ["#4488FF", "#88DDFF", "#FFD700", "#88FF88", "#FF88CC"]
# Torus major radius: distance from the center of the torus to the center
# of the tube.
# Default: 2.0
= 2.0
# Torus minor radius: radius of the tube.
# Default: 0.7
= 0.7
# RK4 integration time step in seconds per frame.
# Values above 0.02 can cause visible trajectory drift on a small torus.
# Default: 0.016
= 0.016
How it works
A geodesic on a Riemannian surface is a curve whose acceleration has no tangential component; equivalently, it satisfies the geodesic equation d2xk/dt2 + Gammak_ij (dxi/dt)(dxj/dt) = 0, where Gamma^k_ij are the Christoffel symbols of the metric. Each symbol is computed analytically from the first and second fundamental forms of the surface, avoiding finite-difference approximations and the numerical noise they introduce. For the torus the metric is diagonal (the parameterization is orthogonal), which collapses the Christoffel computation to two non-zero components. The sphere and saddle use the full symmetric formula.
The ODE is advanced with a classical fourth-order Runge-Kutta integrator. At each frame the integrator evaluates the Christoffel symbols at four intermediate positions and combines the results with the standard 1/6-2/6-2/6-1/6 weights. After each step the velocity is renormalized to unit metric speed (g_ij dui duj = 1) to suppress the slow drift caused by floating-point truncation over hundreds of frames. This is correct because the geodesic equation preserves metric speed exactly; renormalization merely restores the invariant that the integrator breaks weakly.
Each geodesic leaves a trail stored in a fixed-capacity ring buffer. When a new position is pushed, the oldest is silently overwritten. At render time the buffer is iterated from oldest to newest and each vertex is assigned an alpha value equal to (i / N)^2, producing a quadratic fade from transparent at the tail to opaque at the head. The ring buffer never grows or reallocates after initialization, so the per-frame allocation pressure is zero.
Supported surfaces
| Surface | Curvature | Behavior |
|---|---|---|
| torus | Mixed (positive outer rim, negative inner rim) | Geodesics diverge on the inner rim and focus on the outer |
| sphere | Constant positive | All geodesics are great circles |
| saddle | Constant negative | Geodesics diverge exponentially |
Contributing
- Fork the repository.
- Create a feature branch:
git checkout -b my-feature. - Ensure
cargo fmt,cargo clippy -- -D warnings, andcargo testall pass. - Open a pull request against
master.
CI enforces formatting, Clippy warnings-as-errors, the full test suite, and a release build before merging.
License
MIT -- see LICENSE for details.