Skip to content

HarperZ9/studio-engine

Repository files navigation

studio-engine: A native simulation and render engine: generate, critique, refine, and keep the scene.

A native simulation and render engine: generate, critique, refine, and keep the scene.

version license

Studio Engine generates shaders, sound, and motion as replayable creative worlds. A single expression algebra drives everything: each field ships as a WebGL fragment shader for the eye, a portable Web-Audio synth graph for the ear, and a motion timeline with time as a first-class axis. It runs on Python 3.10+ with zero third-party dependencies, exposing a CLI, a local HTTP API, and a reference browser chamber that compiles the shipped GLSL live. Every world writes a receipt you can re-check.

Highlights

  • One algebra, every backend. Each generator is a single strand expression. The engine emits it as a WebGL fragment shader, samples it to score criteria, sweeps it over time for motion, and grounds a Web-Audio synth graph against a baked WAV. The chamber renders the exact math the engine checked, not a re-implementation.
  • Real pixels without a GPU. --render-frames drives a zero-dependency software rasterizer over the emitted program and writes deterministic PNG frames to disk, a strip across the loop period for animatable fields.
  • Watch it think, live. handoff/watch-it-think.html streams the refine loop over Server-Sent Events and plots per-axis margins as they converge, with bounds-clamped sliders that steer parameters mid-run. Rejected steers are shown, never silently applied.
  • 10 generators, one line each to extend. phyllotaxis, gyroid, quasicrystal, attractor, harmonograph, flowfield, metaballs, turbulence, rings, moire. Field generators are one expression plus a criterion; rings and moire are each one line of algebra.
  • A compositor. POST /compose layers multiple organs into one world under a shared composition criterion, with OKLab/OKLCh perceptual palettes across layers.
  • Motion as a first-class axis. Every animatable world carries a Timeline with a witnessed verdict that the loop is seamless at the wrap point and stays legible across the period.
  • Interactive sessions. Create a session over HTTP, inject parameter changes, and get the updated render program back each step. An optional bridge to a native C++ renderer reports honestly when the binary is not built.
  • Zero third-party dependencies. The core engine is Python stdlib only. No pip install is needed to run it from a checkout.

Try it

No install required from a clone:

python -m studio_engine 7 gyroid

Expected output (ids vary with the novelty corpus):

world e97b2c91d927bcaa | 'Gyroid #7'
  steps=7 converged=False final_score=0.0649
  render=glsl-fragment expr_sha=8a94af6a2eba5cb6
  timeline period=0.707566 continuity=verified
  palette=['#7375cb', '#8e7fd8', ...]
  wrote studio-out/world-7.json (+ svg preview + render program)

Or install the package, which adds a studio-engine command that starts the API server:

python -m pip install -e .
studio-engine

Start the API directly and open the reference chamber:

python -m studio_engine.server 8777

Then open handoff/reference-chamber.html in a browser. It compiles the shipped GLSL live, runs point recipes, stacks composites, and plays the synth graph. For live convergence plots and parameter steering, open handoff/watch-it-think.html instead.

Worked example: from seed to PNG frames

python -m studio_engine --render-frames 7 gyroid

This runs the full loop, then rasterizes the emitted render program headlessly:

  rendered 8 PNG frame(s) -> studio-out/frames-7/ (+ frames.json)

studio-out/ now holds the world JSON, an SVG preview, the GLSL render program as text, eight PNG frames sweeping the loop period, and a frames.json manifest binding each frame's sha256 to the program's expr_sha256. Before rendering, the rasterizer reconstructs the expression from the shipped AST, re-hashes it, and refuses to render on a hash mismatch. Open the PNGs in any viewer; the frames tile seamlessly across the period because the timeline verdict says they do.

HTTP API

python -m studio_engine.server [port] serves on 127.0.0.1 (default port 8777, CORS open):

Route What it does
POST /simulate run the loop, return a World
GET /simulate/stream SSE: per-step events, then the world
POST /compose layered composite World
GET /generators, /library, /gallery discovery: generators, organs, pre-built scenes
GET /scene/{id}, /scene/{id}/program, /scene/{id}/filmstrip cached worlds, drop-in render programs, per-step replay
GET /audio/{id}.wav baked sonification
POST /session, /session/{id}/inject, /session/{id}/render interactive steering and re-render
POST /native/render direct native render bridge (reports honestly if the binary is absent)

The handoff/ directory is the frontend integration package: INTEGRATION.md, types.ts, openapi.json, ENDPOINTS.md, examples, and both runnable chambers.

Generators

Generator Channel Criterion (it did not author)
phyllotaxis points golden-angle packing
gyroid field clean tiling (integer frequency)
quasicrystal field 5-fold aperiodic order
attractor, harmonograph points balance / coverage / complexity
flowfield, metaballs, turbulence, rings, moire field contrast / complexity

Each entry in the registry is a declarative binding: parameter seed and bounds, criteria axes, a preview render, and a strand expression (fields) or a point recipe (points). Adding a generator means writing one expression.

The strand substrate

The shader the browser compiles is not hand-written. The engine holds each field as a frozen AST, emits the GLSL field() body from it, and proves the round trip GPU-free: emit GLSL, parse it back, and check that the reparsed AST eval-matches the original to 1e-6 across every generator. The same AST is sampled on CPU to compute the features the criteria judge, and swept over t to build the motion timeline. One source of truth, four consumers.

What's in the box

studio_engine/            the engine (stdlib only)
  strand/                 expr.py (frozen AST), glsl.py (emit + parse-back proof)
                          recipe.py (point recipes), webaudio.py (synth graph)
  model.py                the contract: World / Layer / RenderProgram / AudioProgram / Timeline
  engine.py               the loop          registry.py    the 10-generator data table
  compose.py              the compositor    temporal.py    the witnessed motion timeline
  criteria.py             composable criteria + cohesion   corpus.py   novelty grounding
  raster_renderer.py      headless software rasterizer (PNG frames)
  native_render.py        bridge to the optional native C++ renderer
  certify.py              external structural-fitness oracle (coherence-membrane)
  session.py              interactive steering              server.py   the HTTP API
  organs/                 generators, OKLab palettes, sonify, raster
handoff/                  frontend package: INTEGRATION.md, types.ts, openapi.json,
                          reference-chamber.html, watch-it-think.html, examples/
showcase/                 static showcase with its own fixtures and Node tests

Why it matters

Generated art is usually a dead end: pixels with no structure a person or a later program can inspect. Studio Engine keeps the shader program, sound graph, motion timeline, criteria, and receipt together, so a generated world can be re-rendered, steered, and checked instead of admired once and lost.

(seed, generator, scheme) determines a world for a fixed novelty corpus: same input, same id and sha256s. Every world carries its full refine trajectory, the criteria it was judged against, and a receipt whose artifact hashes cover the JSON, the audio, and any rendered frames, so an experience can be replayed and re-checked later.

Scope and maturity

This is a 0.2.0 engine, not a finished product. It emits render programs and evidence packets; browsers, GPUs, and audio hosts realize them. The immersive chamber is the frontend's build, from handoff/. The dependency-free native GPU renderer is a separate project that this engine bridges to optionally. APIs may still move before 1.0.

Docs and related projects

For developers

python -m pip install -e .
python -m unittest discover -s tests        # 169 tests
node --test showcase/tests/*.test.mjs
python test_forward_delivery_contract.py

See AGENTS.md for the repo operating boundary and CHANGELOG.md for delivery history.

License

AGPL-3.0-or-later, dual-license ready: the author retains copyright and commercial licenses are available.

Zain Dana Harper, small tools with explicit edges. Built with Claude Code; reviewed, tested, owned.

What this believes

This tool is one lane of a family that holds a single belief steady across every surface: knowledge open to anyone who can attain the means; acceptance decided by external checks, never reputation; every result re-runnable; honest nulls first-class; ownership earned by comprehension; learning woven into the work. The full text lives in CREDO.md. The long form of this belief: The Unbundling.


Zentropy Labs · order out of entropy. An independent lab building evidence-first tools that leave a re-checkable artifact behind. Built by Zain Dana Harper in Seattle. The full workbench is at Project Telos.

About

Generate replayable creative worlds with shaders, sound, motion timelines, and receipts.

Topics

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors