The white flashing was the top fade: the live raisers were not repainting it

Oliver: "what is this white flashing while applause in the upper right corner of
the crowd". With the photographers switched off entirely it was still there, so
it was never them — it was mine, from this morning. The top fade is baked into
the cached stand, and drawRaisers was painting a spectator's box straight over
it with only the dim applied. Every time that spectator stood up his box lost
the fade and lit up; every time he sat down it came back. Measured on the canvas:
a 146-luminance jump, twice a second, in exactly the two places raisers sit near
the top of the picture.

Both stand treatments now come from one function each and are applied in both
places. The gradient is built in user space, so filling a raiser's sub-rect with
it picks up the right alpha for free. Probed again after the fix: zero bright
pops during applause and during the wave, against the four hot spots before.

While chasing it, two real detector faults turned up and are fixed too: a blob
may not be a pale block (a re-rolled cream shirt is "new material" by the
stand-turned-person test but nothing rises), and it may not cover something
already bright (a genuine arm drawn over a white shirt deletes a white block,
which flashes just as hard). 94 raisers survive both rules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-21 14:55:13 +02:00
1 parent 93c4a21be5
commit ca3e72d0a9
8 files changed
+81 -47

No files matched your search

+12
View File
@@ -378,6 +378,11 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu
(`HUD`, in portrait logical px — landscape has a shorter band, so the rule is conservative
there rather than over-eager).
Result: 92 of 101 raisers below the board's bottom edge, against 103 of 134 before.
- **A raise must be ARMS OVER STAND, and `_crowdpass.py` tests all three words.** The rolls
repaint clothing as well as posing people, so "was stand, is now person" also catches a
cream shirt that came back a shade brighter (`PALE_MAX`) and a genuine arm drawn over
something already bright, where raising him DELETES a white block (`COVER_MAX`). Both flash
exactly as hard as a real error would.
- **A raiser is ~8x6 logical px, so a pose that appears and holds is invisible.** What reads as
applause is the CYCLE — arms high, hands together, up, down, at about 3.5 Hz — and how many people
are doing it at once (`crowd.pop`). Oliver on the first per-person cut: "when clapping I barely see
@@ -401,6 +406,13 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu
`assets/_sheet_crowd1.png` is the pre-brightening original of the FIRST crowd, kept for history.
## Settled feel decisions — do not regress silently
- **ANYTHING DRAWN OVER THE CACHED STAND MUST CARRY THE STAND'S OWN TREATMENTS.** There are two —
`standDim` and `topFade` — and a raiser box drawn with one of them missing lights up as a bright
rectangle every time that spectator stands. That is what the "white flashing in the upper right
corner of the crowd" was (2026-08-21): the top fade was baked into the backdrop and the live
raisers were not repainting it. Both now come from one function each, called from `paintBackdrop`
and from `drawRaisers`. The gradient is built in USER space, so filling any sub-rect with it picks
up the right alpha for free. Two copies of either number is the same bug waiting again.
- **The frame is dark at BOTH ends.** The run-off apron already took the bottom of the screen down
to near-black below the near baseline; `TUNE.standTop` does the same at the top, so the stand fades
UP out of the dark instead of being cut off at y = 0. Oliver, 2026-08-21: "the bottom of the screen