spriteforge/docs/blender-backend.md

3.5 KiB

Blender backend

The Blender backend launches an external Blender process without a UI:

blender -b rig.blend -P blender_driver.py -- --request request.json ...

No rendered image enters an agent context. The driver writes JSON metadata and NumPy RGBA, view-normal and Z arrays into a temporary directory; the parent process consumes them and deletes the directory.

Blender 5+ pass extraction uses a temporary compositor multi-layer EXR because that release removed the legacy Image.layers API. Official Blender builds bundle OpenImageIO, so this compatibility path adds no Python dependency to the host project. Blender 4 and older retain the direct Render Result path.

demo_actor:
  backend: blender
  rig: rigs/demo_actor.blend
  parts: {body: BodyMesh, head: HeadMesh, weapon: WeaponMesh}
  anims: [idle, walk, attack]
  dirs: 8
  fps: 12
  params:
    render_size: 192x192
    ortho_scale: 4.0
    elevation: 35.264
    samples: 16
    # Manifest clip names can map to arbitrary actions in a reusable source rig.
    actions: {idle: Idle_Loop, walk: Walk_Loop, attack: Pistol_Shoot}
    # Sample the full source actions into compact pre-rendered sprite cycles.
    frames: {idle: 4, walk: 8, attack: 6}
    animation_fps: {idle: 8, walk: 12, attack: 12}
    loop_sampling: {idle: true, walk: true, attack: false}
    direction_offset_deg: 90
    camera_target: [0, 0, 0.9]
    model_rotation_deg: 0
    # One logical Z-sorted layer may contain several Blender objects.
    part_members: {body: [BodyMesh, HelmetMesh]}
    # Or select every renderable object whose name starts with this prefix.
    part_prefixes: {body: actor_body_}

parts values are directly renderable Blender object names. Each object is rendered alone while armatures remain active. The camera is orthographic; direction zero looks from +X toward the origin and subsequent directions rotate counter-clockwise around world Z.

For every animation/direction/frame, pairwise Z comparisons create a back-to-front layer permutation. If both relative orders occur over a material fraction of overlapping pixels, sf validate reports the exact asset, animation, direction, frame and layer pair and advises splitting the component into passes. Cycles fall back to median depth and also produce a warning.

Blender Z is quantized per frame into 8 bits while depth_min/depth_max preserve the camera-space range in world units. Normal-pass X/Y values are stored directly; positive Z is reconstructed by the runtime.

The executable is resolved from params.executable, then BLENDER_BIN, then PATH. On Windows SpriteForge also discovers official versioned installs under Program Files/Blender Foundation, because the Blender installer commonly does not add itself to PATH. Other parameters are render_size, samples, ortho_scale, elevation, camera_distance, engine, timeout_seconds, depth_epsilon, crossing_ratio, dither, actions, frames, loop_sampling, direction_offset_deg, camera_target, model_rotation_deg, part_members, and part_prefixes. Unknown parameters are rejected.

For separately built paper-doll equipment, add the reserved paperdoll_layer tag. Its pivot is intentionally inherited from the body and may lie far outside the small layer bbox; sf validate suppresses only that specific heuristic while still checking hashes, streams, frames and durations. Tags and palette metadata are excluded from the expensive backend-input hash, so reorganizing or retagging a library updates the catalog without rerendering unchanged Blender frames.