Repository navigation
Hunter bird: a blob-tracker shader Setup, with the blob-records contract - #159
Merged
Merged
Conversation
Runnable 2D-canvas sketch of a FundingCAPTCHA Setup idea: the tracker's boxes, IDs and track states drawn as a bird's hunting annotations, seen through its eyelids. Stand-in figures and a simulated 10 Hz tracker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EiZFhwjDY9hyTTEH9BgA9B
…(ADR-0022) Setups can bind "blobs" to read the tracker's records: an 8x3 RGBA32F texture, one stable slot per track, read with texelFetch. Row 0 is the box and row 1 is centroid and velocity, both in Body UV. Row 2 is id, state (tentative, confirmed, coasting, lost), seconds in that state, and nearness. - body_blobs.py finds blobs in the Body itself, so boxes line up with the silhouette, and tracks them with BlobStabilizer in Body pixels. It eases boxes at render rate between camera frames. It only runs while the current Setup reads blobs. - BlobStabilizer.update_tracks() reports every live track, its detection, and expiries. update() is unchanged. - shaders/blob_painter.glsl stands in for the tracker in Shadertoy. On the Pi, --test-input reads the painted Body back and runs the real tracker. - shaders/blob_debug/ is a reference reader, kept outside the rotation. - Fix: the keyboard texture was an integer texture that shaders read as 0, so the painter's Shift, Space and C never worked in the player. - The body painter's head now overlaps its torso, so a painted person is one blob. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EiZFhwjDY9hyTTEH9BgA9B
The spec records the decisions made around the mockup: - strike once per person, then the bird ignores that visitor - keep the iris band, and thin the canopy to a top band - hatching on the lower 40% of each box, denser with nearness - 120 s in the rotation The plan is seven tasks, with a Buffer B state layout and tests that run the real BodyBlobs tracker on synthetic masks. It is not implemented yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EiZFhwjDY9hyTTEH9BgA9B
Buffer B holds SLOT (id, motion, interest, stamped), PREV and HEAD per slot. Motion is record speed plus box size change, minus MOTION_FLOOR (kept at 0.15: a flickering still person reads 0.0, walking 0.57, flailing ~0.8). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ATTN (target, lock, strike), RETICLE, MOOD, BLINK and STAMP texels. Every texel that needs this frame's attention recomputes it with attnNext(), so they agree. A strike names an id; the SLOT accepts it by id next frame. LOCK_RATE 0.32 -> 0.45: at 0.32 the flail test struck at ~5.3 s. Now it strikes at ~4.1 s, and 6 s of walking reaches lock 0.81. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HEAD and the 12 PRINT texels per slot evaluate the same emitsPrint(), so the ring shifts in step. Prints sit just below the box, offset either side of the direction of travel, and age out on their own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paper, wavy slate ground, people as a warm-white fill with an ink outline and slate hatching on the lower 40% of their tracked box (denser when near), and the canopy: two branches, a perch and 29 swaying leaves laid out from the mockup's hash, with side leaves thinned to three per side. The canopy early-outs outside its band, corners and perch box. The world punches in about the stamp point on a strike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Per record: dashed slate box and ? (tentative), wobbly ink corner brackets (heavier on the target), dashed fading brackets and ? (coasting), and a zigzag scribble (lost). A ringing tag with seven-segment id hangs from the top-right corner, yellow on the target, with a rust tick once stamped. A deep-blue velocity arrow, slate footprints under the people, the rust reticle with its lock arc, and the stamp slamming down on a strike. Box-drawing tests feed hand-made records with no Body, since a person's ink outline lies exactly on their tracker box. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Screen space, after the world: the yellow iris band with 110 ink striations and a hatched socket beyond it, closing in with lock and snapping wide on a strike; almond eyelids (hatched paper, yellow eye-ring, ink rim, feather scallops) whose openness is the mood; and the nictitating membrane sweeping across on a blink. Where the socket or lids hide the world, the world isn't drawn. The canopy test now looks at the top centre with the lids wide, since drowsy lids cover the top row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
List hunter_bird among the shader player's Setups in rotation. Constants changed from the plan's starting values: LOCK_RATE 0.32 -> 0.45 (Task 2). MOTION_FLOOR stays 0.15. Checked: - --mock-camera, windowed, 2 min on a desktop: a steady 30.2 fps (the app's cap). Not run on the Pi. - Both tabs compile as GLSL ES 3.00 with Common before the uniforms, as Shadertoy builds them. Not pasted into Shadertoy itself. Not verified: the by-eye mouse pass (--test-input), and "freeze and it loses you" with the real Orbbec camera. On site, run --camera: a visitor who stands still for 5 s must lose the reticle, and one who flails must be stamped within ~3 s (it is ~4 s on the test pattern at these defaults). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes from the whole-branch review: - Walking strikes: lock now builds only above LOCK_ON 0.65, and the speed term is capped at SPEED_CAP 0.7, so walking alone tops out at motion ~0.55. Walkers at 1-3 px per camera frame never strike in 15 s, and flailing strikes at 2.7 s (LOCK_RATE 0.45 -> 0.7). - Steals: interest settles at the motion level instead of filling to 1, so a flailer beats a walker who keeps moving. - Box jitter: PREV is the box low-passed over BOX_EMA_S 0.15 s. Size change is its derivative. A still person at the shipped 480 x 480 scale escapes with +/-8 px of per-side box jitter (it was +/-5). - Frame rate: the lid half of the world-skip test used min where it needed max, so it never fired. Footprints now stop at the first dead print in each slot. Both output pixel-identical frames. New tests: brisk walking never strikes, a flailer steals from a moving walker, and a jittery still person at real scale. The freeze-steal test is gone: a frozen walker now drops out before anyone can steal them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Lock builds only while the target stays put: a new per-slot DRIFT row low-passes each slot's velocity over 1.5 s. A walker's stride swings the box as much as waving arms do; their drift is what tells them apart. - A coasting target is held instead of handed to a rival, so one missed camera frame no longer costs ~80% of the lock. - Rotation.on_load resets the blob tracker on every load and R reload, so a fresh Buffer B never meets ids it has already stamped. - test_shadertoy: the slots-by-rows test no longer lands on a .5 rounding tie, and the tab-line test accepts NVIDIA's "0(2)" as well as "0:2". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
hunter_bird, a FundingCAPTCHA shader Setup that draws the blob tracker's notes as a bird hunting visitors, and the groundwork it needs: a design mockup, ablobschannel source for the shader player (ADR-0022), and the spec and plan. The Setup is in the rotation and plays for 120 s.What's in it
1. The
hunter_birdSetup —ShowControl/FundingCAPTCHA/shaders/hunter_bird/LOCK_ON(0.65) and the person is staying put: each slot's velocity, low-passed over 1.5 s, must be near zero. A walker's stride swings their box as much as waving arms do, so drift is what tells walking from flailing. Walking at any speed or stride tested never strikes; flailing strikes in 2.4–4.2 s.common.glslconstants.docs/FundingCAPTCHA.mdlists the Setup in "Setups in rotation".2. Design mockup —
docs/superpowers/specs/2026-11-04-hunter-bird-mockup.html3. A
blobschannel source for the shader player (ADR-0022, amends ADR-0021)"blobs"and read an 8×3 RGBA32F texture withtexelFetch. Each slot holds a box, centroid and velocity, an id, a state (tentative, confirmed, coasting or lost) and seconds in that state. A slot stays with the same person for that person's whole track.body_blobs.pyfinds blobs in the Body itself, so boxes line up with the silhouette, and tracks them withBlobStabilizerin Body pixels. It runs at camera rate, and only while the current Setup reads blobs. Boxes are eased at render rate between camera frames. Tunables are inshader_app.blobs.BlobStabilizer.update_tracks()reports every live track, its detection, and the ids that expired.update()is unchanged.shaders/blob_painter.glslstands in for the tracker in Shadertoy. On the Pi,--test-inputreads the painted Body back from the GPU and runs the real tracker on it.shaders/blob_debug/is a reference reader. It isn't in the rotation.--test-input.scipyis now always required byshader_app.py.Rotationresets the tracker on every load and R reload, so a Setup's fresh buffers never meet ids it already acted on.4. Spec and plan
docs/superpowers/specs/2026-11-04-hunter-bird-design.mdrecords the design decisions.docs/superpowers/plans/2026-11-04-hunter-bird.mdis the seven-task build plan this PR carries out.Testing
test_hunter_bird.pyhas 45 tests. They run the real Body tracker on synthetic masks (walking, flailing, flickering, pacing, still, two people, a jittering still person) with a fake clock: camera at 10 Hz, render at 30 Hz.make test: 398 passed. The GL tests also pass on Mesa llvmpipe (EGL_PLATFORM=surfaceless LIBGL_ALWAYS_SOFTWARE=1) as well as NVIDIA.Not yet verified
--cameraon site. Someone standing still for 5 s should lose the reticle; someone flailing should be stamped within about 3 s.🤖 Generated with Claude Code