Asset pipeline cannot produce transparent sprites (no alpha, ever) #34
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
cmoriarty/trog#34
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the first real
trog run(#11), by looking at the artifacts rather than the verdict counts.What is wrong
Every sprite and UI asset the pipeline generates is RGB with no alpha channel — the subject painted onto an opaque background. In a Phaser scene each of these composites as a solid rectangle.
From the failed run (
trog-games/a-cozy-fishing-game-2607272154):Why it has never been caught
Two reasons, and both are now closed or understood:
bird.png— a bird on an opaque dusk sky — reasoning that the body had "clean separation against the lighter, warm-toned background bands". The brief said "clean separation from sky", meaning a cutout. Fixed in089724dwith a deterministiccutout_problemgate that runs before the model.Root cause
server/trog_lib/pixel_post.pyconverts to RGB at every stage, so alpha is discarded by construction:And no workflow in
server/trog_lib/workflows/does background removal or emits RGBA.The decision to make
Two approaches, with real trade-offs — worth choosing deliberately rather than by whichever is easier:
pixel_post, thenpixel_postpreserves alpha instead of flattening. One place to change, but automatic matting on 32x32 pixel art is exactly where it is worst — a hue-shifted ramp against a dusk sky has no clean edge to find.Either way
pixel_postmust stop calling.convert("RGB")unconditionally, and the quantise/dither path needs to carry alpha through.Done when
cutout_problemgate (089724d) passes on real generated output rather than rejecting all of it.trog test assetcovers it, so this cannot regress silently again.Related: #11 (found here), #20 (sprite/pixel-art quality), #18 (critic calibration).
Fixed in
2c1a9d1, verified end to end on the live rig.Neither of the two proposed approaches, quite. The ticket weighed workflow-level RGBA against a post-pass and distrusted the post-pass because matting 32x32 pixel art is where matting is worst. That objection is about the raw render — and it stops applying if the cutout runs last. By that point the palette pass has already flattened the backdrop into one or two exact colours, so this is a flood fill over equal pixels, not a guess at an edge. No matting model, no per-workflow work, one place to change.
pixel_post.cutout_backgroundis border-connected, never colour-matched: a pixel is background because it is reachable from the edge through background-coloured pixels. The sky between a bird's wing and its body goes; the identical blue inside its eye stays. Colour-matching would punch a hole through anything sharing a tone with the backdrop, which is exactly the failure this ticket was right to fear.Details worth knowing:
tile_w) — a sheet's border is not each frame's border, and seeding from the sheet alone cuts out the first and last frames only.How it got caught. Not by looking — by wiring the per-item critic in #35.
run_jobhad never calledcritics, so everything the new asset tool generated was committed unjudged. The first asset judged after that gap closed came back:Measured across every sprite generated that session:
chest.png,ws-potion.png,speedknight.png— all RGB, 0.0% transparent.Verification, same prompt before and after, through the full production path (MCP tool → orchestrator → seat → critic → commit):
cutout_problemCommitted:
trog-games/seat-scratch/assets/sprite/alpha-chest.png— corner alpha 0, centre alpha 255, subject intact.Regression cover in
tests/test_pixel_post.py: background cleared, subject kept, the enclosed background-coloured pixel survives, every frame of a sheet is cut,cutout=Falsestill yields RGB for backgrounds, and a round-trip assertingcutout_problemaccepts what the pass produces — the gate that rejected all of this is now the test.Done-when, checked: sprite has alpha with the subject cut out ✅ · the gate passes on real generated output ✅ · covered by tests ✅.
further testing on #35 integrated with other changes, closing this as complete implementation