Skip to content

pet: crisp half-block sprites (nearest sampling, hard shape edges) - #27

Merged
Hmbown merged 2 commits into
mainfrom
claude/nice-bohr-h4i23r
Oct 11, 2026
Merged

Hmbown merged 2 commits into
mainfrom
claude/nice-bohr-h4i23r

Conversation

@Hmbown

@Hmbown Hmbown commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

This fixes the half-block blur on the pet, one of the 0.10.2 pet bugs.

Two things caused the blur:

  • Box-filter sampling (387562b). Sprite::sample became an alpha-weighted box filter, which smears avatar tiles at every scale except 1:1. A 96x96 pack drawn into a 40-cell tank averages neighbouring pixels.
  • Supersampled cove. The terminal whale's cove was rasterized with 4x4 supersampling (2x2 above 64 px). Every shape edge became a fractional-alpha pixel, which Sprite then blended toward the cell background.

Changes:

  • Sprite::sample takes the source pixel under the centre of the target pixel (nearest neighbour).
  • whale_motion/pixels.rs rasterizes one sample per pixel, so a shape edge is either in or out. The cove's deliberate layer opacities stay translucent (behind 0.68/0.9, front 0.82); only the anti-aliased rim goes.
  • Five pet gallery snapshots change: pet-cove, pet-mode, pet-needs-you, pet-pod and pet-reading. Silhouettes lose the half pixel of rim that partial coverage used to paint, and the blended rim colours disappear (pet-cove colour runs drop from 3781 to 2719 lines). No other snapshot moved.

The Codewhale engine vendors this change as codewhale-ratatui 0.1.2; see codewhale-hq/Codewhale#6957. That vendored copy is the crates.io publish source. Publishing 0.1.2 is a founder step.

Evidence

  • cargo test --locked: 787 passed; 0 failed (46 test binaries).
  • cargo fmt --check: clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj


Generated by Claude Code

387562b replaced Sprite's nearest-neighbour lookup with an alpha-weighted box
filter, which smears avatar tiles at every scale except 1:1: a 96x96 pack
drawn into a 40-cell tank averages neighbours into a blur. The terminal
whale's cove was also rasterized with 4x4 (2x2 above 64 px) supersampling,
so every shape edge became a fractional-alpha pixel that Sprite then
blended toward the cell background, and the silhouette read as soft.

- Sprite::sample takes the source pixel under the target pixel's centre.
- The cove rasterizes one sample per pixel, so a shape edge is in or out.
  The cove's deliberate layer opacities (behind 0.68/0.9, front 0.82) keep
  their translucency; only the anti-aliased rim is gone.

The five pet gallery snapshots change accordingly. Silhouettes lose the half
pixel of rim that partial coverage used to paint, and the blended rim colours
disappear (pet-cove colour runs: 3781 -> 2719 lines). No other snapshot moved.

cargo test --locked: 787 passed; 0 failed (46 test binaries).
cargo fmt --check clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Hmbown pushed a commit to codewhale-hq/Codewhale that referenced this pull request Oct 11, 2026
The pet looked blurred in the terminal. Upstream 387562b had replaced
Sprite's nearest-neighbour lookup with an alpha-weighted box filter, which
smears avatar tiles at every scale except 1:1. The whale cove was also
rasterized with 4x4 supersampling (2x2 above 64 px), so every edge became
a fractional-alpha pixel that Sprite then blended toward the background.

Re-vendored from upstream 8f51c6bccadeb11278cda1e2481a116573e5d233
(codewhale-hq/codewhale-ratatui#27):
- `Sprite::sample` takes the source pixel under the target pixel's centre.
- `whale_motion/pixels.rs` rasterizes one sample per pixel. The cove's
  deliberate layer opacities keep their translucency; only the
  anti-aliased rim goes.
Upstream, with this change: `cargo test --locked`, 787 passed, 0 failed
(46 test binaries).

The vendored crate goes to 0.1.2. It is the crates.io publish source, and it
gained DotWhale after 0.1.1 was published, so the packaged codewhale-tui
cannot compile against crates.io 0.1.1. Also changed:
- crates/tui and pet/tui depend on 0.1.2, and both lockfiles are updated
  (cargo metadata --locked passes for the workspace and for pet/tui);
- UPSTREAM.json records the upstream commit and the file hashes;
- the vendored CHANGELOG has a 0.1.2 entry;
- scripts/release/check-versions.sh allows 0.1.2;
- the deconstruction roadmap names 0.1.2.

Publishing codewhale-ratatui 0.1.2 to crates.io is a founder step and
comes before the codewhale-tui publish.

Evidence: cargo fmt --all -- --check is clean. The engine compile and the
pet_watch tests are pending a local test build and hosted CI on
#6957.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
"README matches the components" failed on #27 (run 38139243091):
render-gallery reported six stale pet SVGs (pet.{dark,light}-truecolor-
{1,2,3}.svg). The nearest-neighbour Sprite sampling and one-sample cove
rasterization in 8f51c6b change the pixels those previews were rendered
from. The same change made six README animations stale: subagents-dark,
subagents-light, pet-dark, pet-light, pet-mode-dark and pet-mode-light.

Regenerated with the repository's own tools from the actual buffers:
- `cargo run --example gallery -- --svg target/readme-buffers`, then
  `tools/render-gallery.py ... --readme README.md`. README.md was
  unchanged.
- The pet, pet_mode and subagents examples' `--frames` output, then
  `node tools/render-animation.cjs` (sharp 0.33.5 and ffmpeg).

Evidence: these are the CI gallery steps run locally after
regeneration:
- render-gallery --check: "Verified 141 boards covering all 210
  entries × 2 profiles".
- check-animation: subagents dark/light, pet dark/light and pet-mode
  dark/light each "match all 200 current terminal-buffer frames".
  habitat-motion still matches 80 and showcase 128. Neither moved.
- export-web-motion --check: "Verified 6 native tracks / 762 frames".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
@Hmbown
Hmbown marked this pull request as ready for review October 11, 2026 22:48
Copilot AI balanced review requested due to automatic review settings October 11, 2026 22:48

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@Hmbown
Hmbown merged commit 61abdf9 into main Oct 11, 2026
17 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The bounded sampling and rasterization changes are consistent with the intended crisp rendering, and the updated asset hashes match their GIF files.

0 open findings

What changed in this PR

Updates pet rendering to preserve crisp half-block edges when scaling.

Changes:

  • Replaces box filtering with nearest-neighbor sprite sampling.
  • Removes supersampling from cove rasterization.
  • Refreshes pet preview assets and animation hashes.
File Description
src/​avatar_sprite.rs Uses nearest-neighbor sampling.
src/​whale_motion/​pixels.rs Rasterizes one sample per pixel.
assets/​readme/​pet.dark-truecolor-3.svg Updates the dark pet preview.
assets/​readme/​subagents-light.gif.json Refreshes light animation hashes.
assets/​readme/​subagents-dark.gif.json Refreshes dark animation hashes.
assets/​readme/​pet-mode-light.gif.json Refreshes light pet-mode hashes.
assets/​readme/​pet-mode-dark.gif.json Refreshes dark pet-mode hashes.
assets/​readme/​pet-light.gif.json Refreshes light pet hashes.
assets/​readme/​pet-dark.gif.json Refreshes dark pet hashes.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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.

3 participants