Skip to main content
Euca’s renderer is a real-time PBR forward renderer (wgpu, native Metal on macOS). The camera split follows the engine’s CPU-core/GPU-edge line: the camera pose is a plain Camera resource (CPU state you can read and drive headless), while the rendered output — and the ScreenshotChannel that captures it — is the GPU edge. The headless host boots a Camera resource but no renderer and no ScreenshotChannel, so pose endpoints work and /screenshot is host-only. This page drives every camera and screenshot endpoint against a real local server and shows the exact response. Every command is real; the output below is captured from a headless host.

Point the camera, frame an entity, capture a frame

1. Read the camera. GET /camera returns the camera’s eye, target, fov_y, and projection. The headless host carries a Camera resource (here positioned by the served project), so you get the pose back:
The pose is authoritative CPU state — the same value a render host would draw from. What headless can’t do is render it; that’s the GPU edge, covered by /screenshot below. 2. Set the camera. POST /camera takes optional eye and/or target as [x, y, z], and pins a CameraOverride so an editor’s mouse-orbit won’t snap your shot back:
This actually moves the pose — re-read with GET /camera and eye/target reflect your write. On a render host the rendered view moves with it; headless the pose changes but nothing is drawn. 3. Apply a view preset. POST /camera/view snaps to a named preset — one of top, front, back, right, left, perspective:
The preset is applied to the pose resource headless. A genuinely unknown name (e.g. isometric) returns {"ok":false,"message":"Unknown view: isometric. Use: top, front, back, right, left, perspective"}. 4. Frame an entity. POST /camera/focus targets an entity and pulls the camera to a clamped 5–20 unit distance along the current view direction. Spawn something, then focus it:
The focus reframes the pose around the entity’s transform. (A missing entity_id returns "Missing entity_id"; a nonexistent id returns "Entity 999 not found".) 5. Capture a frame. POST /screenshot re-renders the viewport offscreen, reads it back, and writes a PNG. It needs a ScreenshotChannel resource wired to a live renderer — the one piece the headless host doesn’t have:
Headless returns 503 Service Unavailable — there is no ScreenshotChannel, so there is nothing to capture. On a render host the same call returns 200 with {"ok":true,"path":"/tmp/euca_screenshot_<ts>.png","size_bytes":<n>}. This is the one endpoint that is honestly host-only: do not expect a PNG from the headless host.

Behavior and gotchas

The things you only find out by running it:
  • The camera pose works headless; only rendering doesn’t. GET /camera returns the pose, and every camera write (/camera, /camera/view, /camera/focus) drives that pose resource. What’s absent headless is the GPU edge — nothing is drawn from the pose, and /screenshot can’t capture it.
  • POST /camera reports ok:true and actually moves the pose. Confirm with GET /camera; the new eye/target are reflected. On a render host the rendered view follows; headless it’s pose-only.
  • View presets and /camera/focus succeed headless. They reframe the pose around the named preset or the target entity’s transform; an unknown preset name or a missing entity still returns the matching ok:false.
  • /screenshot is 503 headless, not a problem with your request. It needs a live renderer. Capture from the editor or a windowed build.
  • Setting the camera also pins CameraOverride so an interactive editor’s mouse-orbit won’t fight your framing. This matters only on a render host where an orbit camera is running.

Endpoints

Material, post-process, and fog endpoints live on Materials & post-processing; they share the same render-host-vs-headless split. Keeping appearance out of the authoritative world state is deliberate — see Determinism.

Status

  • Shipped — camera get/set, view presets, entity framing, and offscreen screenshot capture, all backed by the real PBR forward renderer.
  • Host-only output — every rendered result on this page requires a GPU render host (the editor or a windowed build). The headless host carries the Camera pose resource (so camera reads/writes work) but no renderer and no ScreenshotChannel, so nothing is drawn and /screenshot returns 503. This is by design: the headless host runs the simulation and holds the pose, not the renderer.

Camera & render endpoints

Every camera and capture endpoint, with request and response schemas.