File formats
The recipe
Section titled “The recipe”A recipe is one TOML file, schema 1, starting with manfred = 1. The recipe is the whole schema. A reader refuses a newer schema; an unknown key is an error.
The GLB
Section titled “The GLB”manfred build writes glTF 2.0 binary. Each [[object]] is a node named exactly as the object, and each material slot a glTF material named as the recipe’s material, so an app finds both by name. asset.generator is manfred <version>. A mover’s parts carry their group in the node’s extras. The bytes depend on the recipe and its inputs alone: the same recipe gives the same GLB on any machine.
The sidecar, facts dialect
Section titled “The sidecar, facts dialect”With sidecar_dialect = "facts" the sidecar is JSON with sorted keys, in the recipe’s own units and axes (metres, Y up, degrees, linear RGB):
{ "cameras": [ { "fov_y_deg": 35.0, "fstop": 0.0, "name": "main", "orthographic": false, "position": [0.0, 0.35, 0.7], "shift": [0.0, 0.0], "target": [0.0, 0.03, 0.0], "up": [0.0, 1.0, 0.0] } ], "sky": { "intensity": 0.9, "rotation_deg": 0.0 }, "sun": { "color": [1.0, 0.92, 0.82], "irradiance": 2.2, "radius_deg": 0.27, "toward": [-0.45, 0.82, 0.35] }}| Key | Holds |
|---|---|
cameras |
a list in file order: name, orthographic, position, target, up, shift, fstop, and whichever of fov_y_deg, focal_mm, sensor_mm, focus_m and ortho_height the recipe gives |
sun |
toward, radius_deg, color, irradiance |
daylight |
hour, day, latitude, heading, for a daylight sun |
sky |
intensity, rotation_deg, and balance and room when set |
plate |
width, height |
movers |
by group: pivot, axis, travel, clip, clip2 |
look |
exposure, grade |
A key the recipe does not set is left out. The recipe’s [sidecar] table and what generators return are merged over it. manfred::runtime::facts reads it back. An app’s own dialect writes whatever its writer returns (your app’s own generators).
The bake recipe
Section titled “The bake recipe”With [output] bake, manfred build writes a pfx bake recipe in the engine’s bake.toml schema, and bake-materials.toml beside it with every material the GLB names. Every path in it is relative to its folder. The recipe says what each key becomes, and pfx bakes it.
The scene file
Section titled “The scene file”With [output] scene, manfred build writes the engine’s runtime scene, a *.scene.toml (pfx-scene). manfred gui opens one too, read only, and reloads it as it is saved.
manfred render --progress json
Section titled “manfred render --progress json”One JSON object a line on stderr, at most about one a second while tracing. Every line has stage and elapsed_s (wall seconds since the render began).
stage |
Other fields |
|---|---|
stage |
none: the recipe is read and staged |
trace |
adaptive: cap, threshold, gpu_s, fraction (0 to 1, only grows) and eta_s (null before the first round; an upper bound that falls as pixels stop). Every pixel to --spp (--threshold 0): done, total, fraction, eta_s |
write |
none: the picture is being written |
done |
out, mean_samples, most_samples, gpu_s |
manfred diff --json
Section titled “manfred diff --json”{ "materials_differ": false, "nodes": [ { "marks": [ "bounds [0.1000 -0.0000 -0.0000]..[0.2000 0.1000 0.1000] -> [0.0700 -0.0300 -0.0300]..[0.2300 0.1300 0.1300]", "area 0.031388 -> 0.080353" ], "name": "ball" } ], "only_a": [], "only_b": [], "order_differs": false}nodes: each node in both files that differs, with one line a difference inmarks;only_a,only_b: node names in one file alone;order_differs: the same nodes in another order;materials_differ, withmaterials_aandmaterials_bwhen it is true;render, with--render:psnr_db(a number, or"inf"when the pictures are identical),floor_db, and the paths ofa,banddifference, the three PNGs it drew.
A clip’s folder
Section titled “A clip’s folder”manfred clip --out <dir> writes:
frame-0000.png,frame-0001.png…: 8-bit RGBA PNGs, wider than four digits when the last frame needs it. A frame under its own name is whole;clip.txt: the line that made the frames (recipe, camera, frames, size, renderer and samples, variant, sets). A run with a different line into the folder is refused;frames.ffconcat: an ffconcat list holding each frame for its share of a second, to the microsecond, for--videoor any encoder.
A window clip
Section titled “A window clip”manfred gui --clip <dir> --tape <file> writes three files named <tape>-<W>x<H>-<fps>fps:
.master.mp4: x264 High, CRF 14, 8-bit 4:2:0, BT.709 limited range, a keyframe every two seconds;.poster.png: the poster frame, 8-bit sRGB;.json, the manifest:tool(name,version),kind(window-clip),targetandtapeas given,params(size,fps,poster),frames(master, the frame count;seconds;poster, the poster’s frame),outputs(the formats in words),files[](file,rolemasterorposter,bytes,fps,size, and the poster’sframe) andencodes[](file,role,fps,size,args). Readers ignore keys they don’t know.
Exit codes
Section titled “Exit codes”| Code | When |
|---|---|
| 0 | done; manfred diff found no difference beyond tolerance |
| 1 | a refusal after the line parsed, as one line on stderr, manfred <command>: … or <file>:<line>: <key>: …; a failed build, render or encode; manfred diff found a difference |
| 2 | a line it cannot parse: clap’s short error on stderr, then the usage and For more information, try '--help'. |