The scene & material file format for the Hyperion and Theia renderers — a small C++23 library that parses TOML scene/material files and OBJ geometry into plain CPU data structures.
Aether — primordial deity of the bright upper air and pure light the gods breathe; the medium through which light travels. Aether is the medium: it carries a scene's description, untied to any renderer or GPU.
flowchart LR
A["<b>Aether</b><br/>file format"] --> H["Harmonia<br/>shared Vulkan lib"]
H --> Hy["Hyperion<br/>path tracer · ground truth"]
H --> T["Theia<br/>real-time renderer"]
Aether is fully independent: it has no Vulkan, no GPU, and no renderer dependencies (only slang-math for math and toml++ for parsing). It turns text files into plain CPU structs; consumers (Harmonia and the renderers) own all GPU upload.
| Parses | Into |
|---|---|
<name>.scene.toml (TOML scene description) |
aether::SceneDesc (camera, render settings, env, tonemapper, post-tonemap renderer, geometry blocks with TRS + material refs, material-library references) |
<name>.materials.toml (TOML OpenPBR material library) |
aether::MaterialDesc (OpenPBR Surface v1.1.1 parameters + texture references) |
| Wavefront OBJ (geometry only — triangles only; OBJ material directives ignored) | aether::MeshData / aether::MeshGroup (deduplicated vertices + indices, local space) |
Geometry stays in OBJ (bulk vertex/index data); every other element — scene, camera,
render settings, tonemapping, materials — is TOML, so files are small, single-purpose,
and easy to edit (by hand or by an agent). TOML is the best compromise between human
readability and token efficiency: compared to equivalent pretty-printed JSON, the TOML files
save up to one third of the token usage when foreign files are read by an LLM/agent — less
syntactic noise (no braces, fewer quotes), more content per token. Minified JSON would be
denser still, but is no longer readable or editable by humans — and unlike JSON, TOML
supports comments. Geometry is returned in object/local space;
world placement lives on the scene's geometry blocks (TRS). Colors are kept in their declared
input color space, tagged with MaterialColorSpace, so the consumer performs any color-space
conversion.
OpenUSD and glTF are both excellent formats — but for different jobs than Aether's.
glTF is a runtime delivery format: binary buffers optimized for engines to load, not
for humans or agents to read and edit. Its 2.0 core material is metallic-roughness;
OpenPBR is not yet fully supported — it is only partially reachable through material
extensions (KHR_materials_*, still evolving) — and glTF 2.0 does not yet cover complex
scenes. OpenUSD is a powerful composition and interchange system (layering,
references, variants) but is heavyweight and complex — far more than a small hobby
renderer needs, and not something you hand-edit in a text box.
Aether deliberately takes the best of both and stays small and agentic-friendly:
- Human- and agent-readable/editable text (like neither format's binary payloads) — small, single-purpose TOML files with comments, cheap for an LLM to read and generate.
- OBJ for bulk geometry — the one thing that genuinely needs a compact vertex/index container (glTF's buffers, but simpler and ubiquitous), kept separate from the text.
- Lightweight composition — scene/camera/render/tonemap presets referenced and overridden (a small nod to USD layering) without USD's machinery.
- OpenPBR verbatim — material parameters use the exact OpenPBR Surface 1.1.1 names, rather than glTF's or USD's own material models, so nothing is lost in translation.
The result: files small enough to diff and hand-edit, structured enough to compose, and faithful to OpenPBR — the sweet spot glTF and USD each sit to one side of.
- Scene (
<name>.scene.toml): top-levelmaterial_librariesarray;[render],[camera],[tonemap]and[post_tonemap]tables; an ordered[[geometry]]array whose entries havetype = "instance" | "box" | "sphere". Keys are spelled in full words for clarity (samples_per_pixel,environment_map,vertical_field_of_view,mesh,half_extents,material, …). The[render]table may select the scene-referred working color space viaworking_color_space = "lin_rec2020_scene" | "lin_rec709_scene"(absent → consumer default, Rec.2020); consumers convert all assets to it on load. - Camera preset (
<name>.camera.toml): a small standalone preset file withtranslate, rotation (rotatequaternion orrotate_x/rotate_y/rotate_zEuler),vertical_field_of_viewandev100keys. It is meant to be referenced from the scene file's[camera]section. - Setting presets (
presets/<name>.<group>.toml): the[render],[camera]and[tonemap]and[post_tonemap]sections may carry areference = "presets/…"key pointing at a standalone preset file (top-level keys, same shape as the inline section). The referenced file is applied first as a base, then any inline keys override it (local wins). Settings shared across scenes therefore live in a single deduplicated preset file (e.g. all Cornell scenes sharepresets/cornell.camera.tomlandpresets/preview.render.toml). References resolve relative to the scene directory. - Materials (
<name>.materials.toml): one TOML table per material (keyed by name), using OpenPBR Surface v1.1.1 parameter names verbatim; optional top-levelcolorspaceandmodel(default"openpbr"— the material model tag, anticipating additional material models in the future). Texture bindings use Aether'smap_*keys. - OBJ: geometry only. Non-triangle faces are skipped and all
usemtl/mtllibdirectives are ignored — materials are assigned exclusively from the scene file.
See tools/README.md for the Blender scene exporter and the MaterialX-to-TOML
converter. The Blender addon exports a .scene.toml, a matching .camera.toml
and OBJ files; OpenPBR materials stay in TOML and can be authored separately or
generated from MaterialX OpenPBR libraries.
Tip: in VS Code, install the Even Better TOML extension for syntax highlighting, formatting, and (with a JSON Schema) live validation of the
.tomlfiles.
Requirements: CMake 3.28+, a C++23 compiler, vcpkg (provides toml++; slang-math is pulled via CMake FetchContent).
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="<vcpkg-root>/scripts/buildsystems/vcpkg.cmake"
cmake --build buildGoogleTest-based unit tests (pure CPU — no GPU required):
cd build && ctest --output-on-failureHyperion, Theia and Harmonia pull Aether via CMake FetchContent and link the
aether::aether target.
| Library | Purpose |
|---|---|
| slang-math | Vector / quaternion math (header-only, via FetchContent) |
| toml++ | TOML parsing for the .scene.toml / .materials.toml formats |
| GoogleTest | Unit testing (tests only) |
The material model follows the OpenPBR Surface specification; MaterialX is the
canonical node reference used by the tools/ MaterialX→TOML converter.
- OpenPBR Surface v1.1.1 — Academy Software Foundation. https://academysoftwarefoundation.github.io/OpenPBR/ · reference repo
- MaterialX — specification and node library (OpenPBR
open_pbr_surface). https://materialx.org/ · https://github.com/AcademySoftwareFoundation/MaterialX - Wavefront OBJ — geometry container (triangles only; material directives ignored).