Skip to content

CI, a Nishita sky demo, demo docs, and the unpushed engine work chaos-rpg depends on - #1

Merged
Mattbusel merged 13 commits into
mainfrom
ci-and-demos
Sep 25, 2026
Merged

Mattbusel merged 13 commits into
mainfrom
ci-and-demos

Conversation

@Mattbusel

Copy link
Copy Markdown
Owner

What this does

  1. Brings main up to the engine that chaos-rpg actually builds against. The local checkout at C:\proof-engine (which chaos-rpg uses by path) was 9 commits ahead of GitHub, from March 31 to September 12: the release-build fixes, the HDR UI world pass, engine.fx, the bloom pyramid, GPU density entities, particle skinning, the synthesiser, and the change that made the unit tests compile at all. They are included here unchanged, with today's README rewrite merged in on top (the "screen pipeline" section from the local README is kept, the rest is today's version).
  2. Adds CI (.github/workflows/ci.yml):
    • Ubuntu: cargo build --all-targets, library unit tests, integration and binary tests, doc tests. Cached with Swatinem/rust-cache. Only ALSA headers are installed; nothing opens a window or needs a GPU.
    • Windows and macOS: cargo build --examples, so "the demos build from a fresh clone" is checked on all three platforms.
    • No clippy or rustfmt gate: the crate is 570k lines that have never been formatted or linted, and turning either on would mean a whole-tree rewrite.
  3. Known failing tests are listed, not hidden. cargo test --lib has 4834 passing and 79 failing tests. These never ran before September (the test modules did not compile), so this is the baseline, not a regression. They are named one per line in ci/known-failing-tests.txt; ci/test-lib.sh skips exactly those names with --exact, and ci/run-known-failing.sh runs only them. Nothing is #[ignore]d or deleted, and deleting a line re-enables the test in CI.
  4. Fixes, each covered by tests that were failing and now pass:
    • Debug-build integer overflow panics in the hash functions of particle::density_entity (used by density entities, so debug runs of those panicked), volumetric_fog, editor::terrain and the editor::map_editor loot roll. 16 unit tests go from failing to passing.
    • Bloom seam: every pyramid level shared one half-resolution scratch texture, so each smaller level blurred its bottom-left corner and read back clear colour for the rest, showing up as a brightness step along the screen's vertical and horizontal centre lines. This fix was sitting uncommitted in C:\proof-engine since Sept 15; I saw the seam in captures of the new sky demo (bloom on: step at x = width/2; bloom off: none) and applied it as is. It builds and the pipeline runs; I could not re-capture a frame after applying it (see below).
    • benches/particle_bench.rs did not compile (MathParticle gained fields).
    • Five doc examples did not compile against the current API; fixed to match it.
  5. New demo, cargo run --release --example sky: the first of the advanced lighting modules wired into a demo. Every sky cell is nishita_sky::compute_sky_color for its view direction, recomputed every frame as the sun crosses the sky; mountains take their light from the sky just above the horizon; stars fade in at night. Space pauses, Up/Down change speed, Esc quits. Only public API is used; no engine code changed for it.
  6. README: CI badge; per-platform prerequisites (ALSA headers on Linux; apotheosis needs GL 4.3 compute shaders, which macOS does not have); a Demos table describing each example against its source; the close-up convergence screenshot re-cropped into assets/convergence-close.png without the NVIDIA overlay toast (the original with the overlay is removed); status section updated.
  7. Release prep: version 0.2.0 (MathParticle gained public fields, so struct literals break), CHANGELOG.md, and exclude so screenshots and tooling stay out of the crate (4.6 MiB compressed). cargo publish --dry-run passes.

Compatibility

chaos-rpg (current local tree) checked with its proof-engine path pointed at this branch: cargo check -p chaos-rpg --features full-graphics succeeds. No public API was removed or renamed.

Checked locally (Windows)

  • cargo build --all-targets, sh ci/test-lib.sh (4834 passed, 79 skipped), cargo test --test '*' --bins, cargo test --doc (28 passed)
  • editor/ builds
  • sky ran and was captured at several times of day before the bloom fix.

UiLayer, UiLayerRenderer and ui_primitives (1,280 lines: panels, bars,
ghost HP bars, aligned text, sprites) were fully written and reachable
from nothing. No game could draw a HUD.

- Pipeline::render_ui builds instances from a UiLayer's draw queue and
  paints them after post-processing, straight to the default framebuffer,
  so panels and text are not smeared by bloom, chromatic aberration or
  grain. Depth test off, alpha blending on, one copy per instance — the
  3D pass's oversampling would smear UI text.
- ProofEngine::ui exposes the layer; run_ui drives a game loop that calls
  update *before* rendering. The existing run/run_with_overlay call the
  update closure after Pipeline::render, so anything a game drew appeared
  a frame late. run_ui also clears the layer each frame, making it
  immediate-mode.
- Pipeline::render_size / ProofEngine::render_size expose the framebuffer
  dimensions. Screen-space passes must project against these rather than
  the window size; using the wrong one magnifies the whole UI.

Verified by CHAOS RPG's Full Graphics frontend, which now renders its
title, character creation, floor navigation, combat, character sheet,
settings, scoreboard and game-over screens through this path.

Claude-Session: https://claude.ai/code/session_016omDcugLMYPFFoFF28HTyh
Screen-space UI was unusable for a real interface. All three of these
were found by looking at the screen, not by reading the code.

1. The whole UI rendered upside down. The pass draws straight to the
   default framebuffer after post-processing has composited, and that
   content arrives already flipped relative to the FBO passes, so
   projecting y=0 to the top landed it at the bottom. The window
   decorations staying upright is what gives it away.

2. Every glyph carried faint marks around it, and solid rules broke into
   dashes. The atlas is converted to a signed distance field across the
   whole image with a six-pixel spread, but cells were packed edge to
   edge, so each glyph's field leaked into its neighbours. Cells now sit
   in an eight-pixel gutter, wider than the spread, and UVs span the
   glyph box only. A half-texel inset additionally keeps LINEAR
   filtering off the seam.

3. Filled rectangles were never drawn. UiLayerRenderer built them into a
   separate rect_instances buffer that nothing uploaded, so panel fills
   and bar backgrounds were computed every frame and discarded. They now
   go through the same instanced glyph batch as everything else.

   Fills sample a single texel from deep inside the full block rather
   than stretching the glyph: a distance field stretched over a
   panel-sized quad turns its edge falloff into a wide gradient, which
   reads as a blurry smear.

Pipeline::render_size and ProofEngine::render_size expose the
framebuffer dimensions, which screen-space passes must project against
rather than the window size.

Claude-Session: https://claude.ai/code/session_016omDcugLMYPFFoFF28HTyh
Design direction: Russian constructivism crossed with medieval
illumination. Constructivism supplies the structure — vermilion, black
and cream, hard geometry, no glow for its own sake. Illumination
supplies the warmth: gold leaf, ultramarine ground, parchment.

VISUALS

All five colour ways rebuilt around that. Nothing is a pure hue:
vermilion is a lead pigment, gold is not yellow, and the blacks are soot
— a flat #000 is the one colour neither tradition contains, and a test
now enforces that. Themes renamed for the player (Constructivist,
Illuminated, Vermilion, Ultramarine, Suprematist) while keeping their
identifiers so existing settings still load.

Panels are drawn as filled rules rather than box-drawing characters. The
font's box glyphs are narrower than the cell they are spaced on, so runs
of them rendered as dashed lines with gaps. Rules also suit the look:
constructivism is hard geometry, not an ASCII impression of it. Titles
sit in a notch cut from the top rule.

Text is larger (88 columns rather than 104) and, with the engine-side
atlas fix, has no artefacts around it.

MUSIC

The score was walking up a scale, which is not a tune. Each of the nine
vibes now has a written melody — pitches and rhythms, built on a short
figure that repeats with variation — over a sustained drone.

The drone is medieval organum, a held root and fifth, and it is what
stops modal writing from sounding like practice. Combat is phrygian, so
the flat second does the work; desperation is locrian, with no stable
fifth to rest on; corruption is whole tone, so nothing ever arrives.
Corruption's drone is a tritone on purpose.

Melodies are transposed by scale degree rather than written in absolute
pitches, so one phrase carries into whatever mode the situation calls
for. Tests assert the tunes change direction, repeat pitches, and vary
their note lengths — a metronome and a scale run both fail them.

ALSO

Full Graphics is now the default render mode: someone double-clicking
the game expects a window, not a terminal. The saved setting on this
machine had been left on Terminal UI by earlier testing.

374 tests. Zero clippy warnings.

Claude-Session: https://claude.ai/code/session_016omDcugLMYPFFoFF28HTyh
- anim/particle_skin: bind a particle cloud to a skeleton so poses, blends
  and IK move matter, with an integration test
- entity/cohesion and springs: stronger binding model, entity_physics test
- postfx: dual-filter bloom with a nine-tap tent upsample, reworked
  composite pass, exposed in config
- ui_layer: more primitives wired through the renderer

Claude-Session: https://claude.ai/code/session_01MBrnWGcuCN1NsMW5zZACjm
The UI layer used to paint everything after post-processing, straight
onto the finished frame. A game drawing its figures, rooms and effects as
screen-space matter got no bloom, no tonemap, no grade on any of it.

- UiPass: particle clouds, filled rects and panel fills paint into the
  HDR scene buffer before post-processing; text, borders, bars and
  sprites stay sharp on top. begin_world/begin_hud/end_pass override.
- Scene and bloom targets are RGBA16F; render_scale is honoured.
- ScreenFx on the engine: shockwaves, flashes, light shafts (explicit or
  from the brightest thing on screen), floor reflection, heat haze.
- Composite: screen-space indirect light, light shafts, lens flare,
  reflection, haze, shockwave refraction, flash.
- FXAA 3.11 pass between the composite and the HUD, off by default.
- Camera trauma now decays in run_ui; it was added and never ticked.
- vsync, on by default.

Claude-Session: https://claude.ai/code/session_01MBrnWGcuCN1NsMW5zZACjm
… isosurfaces

- 83 lib-test compile errors fixed: tests updated to the structs and
  functions that actually exist, two tests of features that never
  existed removed, a private box mesh builder exposed to its test.
- particle::gpu_density: the module colossus and sculptor import. A
  bone-described figure drawn as millions of particles derived on the
  GPU from the instance index; OpenGL 3.3, no per-particle data. Wired
  through init_gpu_density and queue_gpu_density_entity.
- metaball::marching_cubes: the stub that returned an empty mesh is now
  a marching tetrahedra extractor with gradient normals.

Claude-Session: https://claude.ai/code/session_01MBrnWGcuCN1NsMW5zZACjm
- Light map: engine.fx.lights and fx.ambient. The glyph pass writes an
  occluder buffer (matter, not floors or panels); the light pass marches
  shadows through it from every light. Composite multiplies the scene by
  it, with emissive matter lighting itself.
- Persistence: last frame's scene decays under this one, for trails.
- Audio output honours what a source asks for: log pitch range, detune,
  pitch envelope, second partial, noise mix, biquad and comb filters,
  drive, fade-in and fade-out, start delay. Separate music and effects
  buses, music ducking, a master reverb send, a soft limiter.

Claude-Session: https://claude.ai/code/session_01MBrnWGcuCN1NsMW5zZACjm
@Mattbusel
Mattbusel merged commit a9ef2d3 into main Sep 25, 2026
3 checks passed
@Mattbusel
Mattbusel deleted the ci-and-demos branch September 25, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant