78 lines
3.5 KiB
Markdown
78 lines
3.5 KiB
Markdown
# Blender backend
|
|
|
|
The Blender backend launches an external Blender process without a UI:
|
|
|
|
```text
|
|
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.
|
|
|
|
```yaml
|
|
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.
|