GhostRender

Decoupling Math from Pixels

The Problem

Why calculate physics in Python when Rust exists?

We love Blender's Python API. It's flexible, accessible, and great for tooling. But when you're calculating millions of particle positions or complex wave functions per frame, Python's Global Interpreter Lock (GIL) and dynamic typing become a bottleneck.

The frame rate drops. The viewport stutters. The artist waits.

The Solution

GhostRender proposes a radical shift: The Pipeline Approach.

Instead of asking Blender to think, we only ask it to draw. We move the heavy lifting to Rust, a systems programming language known for blazing speed and memory safety.

Rust The Orchestrator

Calculates math, generates scripts, and manages threads.

Parallel The Pipeline

Splits 1800 frames into chunks for concurrent rendering.

Blender The Worker

Multiple headless instances render video parts.

The Code

Here is the heart of the engine. Rust spawns multiple Blender instances, each rendering a chunk of the animation in parallel.

// src/main.rs
    for i in 0..CHUNKS {
        let start_frame = i * frames_per_chunk;
        let end_frame = (i + 1) * frames_per_chunk - 1;
        
        // Spawn a thread for each chunk
        let handle = thread::spawn(move || {
            let output_path = format!("//part_{}_", i); 
            
            Command::new(&blender_bin)
                .arg("-b")
                .arg(BLEND_FILE)
                .arg("-o").arg(&output_path)
                .arg("-s").arg(start_frame.to_string())
                .arg("-e").arg(end_frame.to_string())
                .arg("-a") // Render animation
                .spawn()
                .expect("Failed to spawn blender worker");
        });
        handles.push(handle);
    }

This approach saturates the CPU cores, drastically reducing render time for long animations.

The Evidence

Talk is cheap. Here is the artifact produced automatically by our CI pipeline on the latest commit.

10 cubes, 1800 frames (30s), rendered in parallel on 4 chunks.

The "Gotchas"

Building this wasn't free. We learned that headless rendering on Linux requires a virtual framebuffer (XVFB).

Error: "Unable to open a display"

We fixed this by installing xvfb and libgl1-mesa-dri in our CI environment, and running Blender with xvfb-run.

Another challenge was stitching the video parts. We used Blender's Sequence Editor (via another generated script) to concatenate the parallel chunks seamlessly.