Skip to content

feat(ui): double the blocks arena's resolution with quadrant glyphs - #27

Merged
puradox merged 4 commits into
mainfrom
quadrant-glyph-arena
Jul 20, 2026
Merged

feat(ui): double the blocks arena's resolution with quadrant glyphs#27
puradox merged 4 commits into
mainfrom
quadrant-glyph-arena

Conversation

@puradox

@puradox puradox commented Jul 19, 2026

Copy link
Copy Markdown
Owner

The half-block fallback (1×2 sub-pixels per cell) looked rough on terminals without kitty graphics — macOS Terminal especially. This sharpens that fallback path and makes it cheap at full screen; kitty mode is untouched.

Quadrant glyphs — 2× the resolution. blit_bevy_arena becomes quadrant_blit: each cell is a 2×2 grid of sub-pixels fitted to a Unicode quadrant glyph (quad_cell splits the four on the widest-spread colour channel, chafa/notcurses-style), doubling the arena's resolution on block-element glyphs every monospace font carries (no sextant tofu risk). Supersample is QUAD_SS=4; the cols×2·rows image aspect is unchanged, so no camera math moves. The headless snapshot re-expands each glyph via quad_pattern, and the die numbers still composite on top.

Half-blocks where the quadrants seam. macOS Terminal.app draws the 2×2 quadrants through its font, leaving visible seams. resolve sniffs TERM_PROGRAM (quadrants_tile_cleanly) and there falls back to seam-free half-blocks — GraphicsMode::Blocks { half_block } carries the choice. Every other terminal keeps the sharp quadrants.

Parallel blit. The per-cell box-average + 2-colour fit is the blocks path's per-frame CPU, and it scales with arena area, so at full screen it was single-thread-bound. quadrant_blit now fits the cells across cores by row band with thread::scope (rows independent, output chunks disjoint → byte-identical to serial, no synchronization), reusing the cached graphics::core_count() that pack_rgb already relies on. Full-screen compose drops ~6× (measured 24ms → 3.9ms in a debug build at a 320×90 terminal; a release build is roughly ⅒ that).

Blocks vs kitty at full screen, evaluated before merge. Blocks stays heavier than kitty at large sizes, but that's the terminal write, not our compute: the block path repaints a full truecolor cell grid every animated frame (~0.5–0.8 MB/frame at full screen — one glyph + fg + bg per cell), which is inherent to text rendering and the same volume the old half-blocks wrote. Kitty ships the arena as one image via a ~50-byte t=f path reference and is unaffected. So this PR adds no lasting per-frame CPU over the old fallback, and kitty remains the fast default wherever it's available.

Validation. cargo fmt, clippy -D warnings, and the full suite (61 binary + 64 core) are green. New GPU-free tests pin the glyph-table round-trip, the two-colour fit, and blocks == render_bevy byte-for-byte (so the parallel blit matches the serial one exactly). Renderer eyeballed via the headless TINHORN_BEVY_SNAPSHOT path.

🤖 Generated with Claude Code

@puradox puradox changed the title feat(ui): render the blocks arena with quadrant glyphs feat(ui): double the blocks arena's resolution with quadrant glyphs Jul 19, 2026
puradox and others added 3 commits July 19, 2026 05:18
The half-block fallback (1×2 sub-pixels/cell) looked rough on terminals without kitty graphics, especially macOS Terminal. Replace blit_bevy_arena with quadrant_blit: each cell is a 2×2 grid of sub-pixels fitted to a 2-colour Unicode quadrant glyph (quad_cell splits the four sub-pixels on the widest-spread channel, chafa/notcurses-style) — double the resolution, on block-element glyphs every monospace font carries (no sextant tofu risk). Bumps the supersample to QUAD_SS=4 for a square-ish 2×4 render block per sub-pixel; the cols×2·rows aspect is unchanged, so no camera-math change. The headless snapshot (PNG + text dump) re-expands each glyph via quad_pattern. Numbers still composite on top. New tests pin the glyph-table round-trip and the 2-colour fit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The quadrant glyphs render pixel-perfect on modern terminals but macOS Terminal.app draws them through its font, leaving visible seams between cells (the '\''misaligned lines'\'' — its half-block ▀ tiles fine, the 2×2 glyphs don'\''t). So GraphicsMode::Blocks now carries a half_block flag: quadrant_blit fits each cell with quad_cell normally, or half_cell (a seam-free ▀, top-row avg fg / bottom-row avg bg) when set. resolve() sets it from quadrants_tile_cleanly (TERM_PROGRAM != Apple_Terminal), so Terminal.app gets the seamless-but-coarser half-blocks and every capable terminal keeps the crisp quadrants. The debug overlay shows quad vs half. New tests pin the detection and half_cell.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
quadrant_blit was a single-threaded per-pixel pass — box-averaging the
supersampled render and fitting each cell to a 2-colour quadrant glyph —
that scales with the arena area, so at a full-screen size it dominated the
blocks path's per-frame CPU. Split the fit across cores by row band with
thread::scope (rows independent, output chunks disjoint → byte-identical to
serial, no synchronization), then write the fitted cells into the ratatui
buffer serially. Reuses the cached graphics::core_count() (now pub(crate)),
so both readback passes — pack_rgb and this — share the one-time
available_parallelism lookup.

Full-screen blocks compose drops ~6x (debug 24ms→3.9ms at 320x90, ~0.4ms
release), erasing the extra CPU the quadrant switch added over the old
half-block fallback. The dominant full-screen cost — the per-frame truecolor
cell grid written to the pty — is inherent to text rendering and unchanged;
kitty stays the fast path where available.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@puradox
puradox force-pushed the quadrant-glyph-arena branch from c299061 to a90f40e Compare July 19, 2026 12:19
…where

macOS Terminal.app draws the 2×2 quadrant glyphs with faint seams, so the
fallback rendered the arena there in coarser `▀` half-blocks. In practice the
seams don't warrant a second code path, so render quadrant glyphs on every
terminal. This reverts the `half_block` flag, `quadrants_tile_cleanly`,
`half_cell`, the resolve/call-site plumbing, and their tests, keeping the
parallel `quadrant_blit`. Also points the graphics.rs/scene doc comments at the
quadrant blit (they still named the old half-block blit and the renamed
`blit_bevy_arena`).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@puradox
puradox merged commit 5ef5ca5 into main Jul 20, 2026
2 checks passed
@puradox
puradox deleted the quadrant-glyph-arena branch July 20, 2026 01:03
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