No description
  • C# 76.4%
  • HLSL 15.9%
  • PowerShell 5.3%
  • C++ 1.8%
  • Python 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-05-08 16:04:52 +01:00
docs Use CultLib for live reload state 2026-05-08 12:42:08 +01:00
scripts Add live runtime assembly reload 2026-05-08 16:04:52 +01:00
src Add live runtime assembly reload 2026-05-08 16:04:52 +01:00
.gitignore Replace Stride shell with Vortice spine 2026-05-08 01:33:13 +01:00
Aquarium-Engine-Icon.png Use Aquarium icon and Unicode window title 2026-05-08 14:53:06 +01:00
Aquarium.Engine.slnx Add live runtime assembly reload 2026-05-08 16:04:52 +01:00
global.json Bootstrap Stride-hosted engine shell 2026-05-08 00:32:51 +01:00
README.md Add live runtime assembly reload 2026-05-08 16:04:52 +01:00

Epiphany Aquarium Engine

Epiphany Aquarium Engine icon

C# engine-core seed for the next Epiphany Aquarium line.

This repo starts after the web and Rust prototypes taught the expensive lesson: the Aquarium wants an owned renderer, owned state model, and owned interaction grammar. Stride can stay on the shelf as reference material, but the runtime is Aquarium-owned: window, renderer, state, and interaction grammar all belong here.

Intent

  • C# host with renderer architecture kept legible in Rider.
  • Vortice/D3D11 first, with the native boundary kept explicit.
  • Grid-centered camera and world-space interaction invariants as first-class engine contracts.
  • Diegetic UI surfaces driven by Aquarium objects instead of admin chrome.
  • CultNet for Epiphany communication.
  • CultCache for settings, persistent client state, and reload recovery.
  • Procedural audio and visual state treated as coupled signals.

Borrowed Lessons

  • The web client proved the interaction grammar: objects first, panels only as local unfold surfaces.
  • The Bevy prototype proved the renderer direction: raymarched bodies, Grid-space fields, HDR, bloom, and camera/Grid invariants.
  • The Rust synth work proved the audio module deserves its own small, sharp API.

First Build Target

Create the smallest C# executable that opens a window, owns the camera/Grid invariant, and renders one sun plus orbiting planets with diegetic labels. Everything else earns its way back in.

Run

Aquarium currently expects the sibling CultMath and CultLib repos at E:\Projects\CultMath and E:\Projects\CultLib, or the equivalent ..\..\..\CultMath / ..\..\..\CultLib paths from the engine project.

dotnet build Aquarium.Engine.slnx
dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj

For iteration while an Aquarium window is already open, use the dev reload runner instead of dotnet run:

.\scripts\dev-reload.ps1

It builds an apphost executable into a fresh disposable slot under artifacts\dev-reload, records the slot/PID in PowerShell CLIXML, and launches the runtime with a MessagePack CultCache store at artifacts\dev-reload\cultcache\aquarium-client.msgpack. The previous script-owned process is stopped only after the replacement build succeeds. This keeps MSBuild away from the locked normal bin\Debug output while a live window is still open.

For automatic rebuild/restart on source changes, use the watcher:

.\scripts\dev-watch.ps1

The watcher polls source files, waits for writes to settle, builds into a new slot, and only replaces the running Aquarium after the new build succeeds. If a build fails, the previous good process keeps running and that same broken source fingerprint is not retried until files change again.

Shader edits do not restart the process. The dev reload runner passes the source Aquarium.hlsl path into the live app, and the renderer polls that file, compiles changed shaders in the running process, then swaps the D3D shader objects only after compilation succeeds. A bad shader edit leaves the previous working shaders bound and writes the compiler failure to stderr.

Live gameplay/runtime code is split into Aquarium.Engine.Live behind Aquarium.Engine.Contracts. The host loads that live DLL through a collectible assembly load context, while dev-watch.ps1 builds live-only changes into artifacts\dev-reload\live-slots and updates live-current.txt. The running host sees the pointer change, loads and starts the new runtime first, then disposes the old one only after the replacement is valid. A bad live DLL leaves the previous runtime alive and reports the reload failure to stderr. Successful reloads rehydrate through CultCache without restarting the window or D3D device. Host, renderer, contract, project, and script changes still rebuild and restart the apphost.

Runtime live state is a typed CultCache document, not a loose sidecar file. The first document is epiphany.aquarium.live_state, currently banking camera target, yaw, pitch, distance, time, and save generation every few frames so a reload can rehydrate without pretending memory is vibes.

Stop the script-owned Aquarium process:

.\scripts\dev-stop.ps1

Headless smoke:

dotnet run --project src\Aquarium.Engine\Aquarium.Engine.csproj -- --headless

Headless reload smoke without touching the normal build output:

.\scripts\dev-reload.ps1 -Headless

Headless watch smoke:

.\scripts\dev-watch.ps1 -Headless

The first cut opens a Win32 window directly and owns a D3D11 swapchain through Vortice. No Stride runtime, no asset protocol, no borrowed game loop wearing a fake mustache. See docs/vortice-spine.md.

Current camera controls are documented in docs/input.md.