Skip to content

Editor hardening, test baseline, CI validation, export fixes, and the blob-tracking layer#104

Merged
git-chad merged 4 commits into
mainfrom
editor-hardening-and-fixes
Jul 7, 2026
Merged

Editor hardening, test baseline, CI validation, export fixes, and the blob-tracking layer#104
git-chad merged 4 commits into
mainfrom
editor-hardening-and-fixes

Conversation

@git-chad

@git-chad git-chad commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Consolidates #92#101 (issues #81, #84#91) plus the full blob-tracking effect layer implementation.

Blob tracking (#91) — complete implementation, ready for in-browser testing

Editor (feat: add blob-tracking effect layer):

  • BlobTrackingPass: 64×36 motion+luminance analysis with previous-frame feedback, non-blocking readRenderTargetPixelsAsync readback (live mode consumes last frame's buffer, one frame of latency by design), CPU tracker, 32-blob float DataTexture table, aspect-correct square/circle/diamond SDF composite with shapeScale/invert, outputMode: decorated | mask (mask = white fills on black for the existing compositeMode: "mask" machinery), CCTV decoration overlay (outlines, #04 0.62,0.41 labels, straight/curved connecting lines, decaying trails) on a CPU canvas — never present in mask output, rewind reset, and prepareForExportFrame that awaits the readback and steps once per distinct timestamp for deterministic exports
  • One inner-effect child pass (21 pass-backed effect types, own switch — no factory cycle) rendered into a private half-float RT and mixed inside shapes; params edited via a dedicated sidebar section writing through the hidden innerEffectParams JSON param (undo/change-detection for free, no keyframes in v1)
  • Registered everywhere: type union, registry (Detection/Shapes/Inner Effect/Decorations groups), factory, layer picker, shader-export unsupported list

Package (feat: mirror the blob-tracking layer): tracker copied verbatim, pass adapted to the package runtime (steps on the runtime clock, decorations degrade without document), registered in ShaderLabEffectLayerType + createPass, ShaderLabBlobInnerEffect exported, READMEs updated, minor changeset.

Testing checklist (needs a WebGPU browser)

  1. Add a video layer + Blob Tracking layer → boxes appear over moving regions and follow them
  2. Pause the video ~2 s → auto mode falls back to luminance boxes; motion re-arms it
  3. Toggle persistent tracking off → per-frame re-detection (glitchy ids)
  4. Shape type/scale/invert; outputMode: mask + layer compositeMode: mask → stencils content below, no decorations in the mask (zoom in)
  5. Inner effect: pick e.g. halftone/dithering → renders inside shapes only, params tweak live (pay attention to particle-grid + voxel (compute) and bloom/pixel-sorting/smear/circuit-bent (multi-step))
  6. Decorations: outline/labels/lines/curved/trails toggles; trailDecay 0 removes trails
  7. Scrub the timeline backwards → no ghost tracks
  8. Export the same 3 s composition twice → frame-identical (determinism)
  9. Known orientation risk (documented in-code): if the whole effect reads vertically mirrored vs the content, it's a single-line screenUv.y flip in buildEffectNode — flagged with a NOTE(orientation) comment

One deliberate gap: the picker preview image (/examples/blob-tracking.webp) needs a screenshot of the working effect — entry ships without a preview until then.

Everything else (unchanged from before)

  • Lint cleanup; first test suite (76 tests incl. tracker + inner-effects); CI validates the app; .lab import hardening (zod + consent gate + SVG cap); lazy export dialog + muxers (−99.9 KB); encoder close on failed exports + video load timeout; onRuntimeError(null) fix; renderer dedup inventory + design; localeCompare perf fix

Verification

bun test (76 pass), bun run typecheck:tsc, package typecheck, bun run lint, bun run build:runtime, full bun run build, and bunx changeset status (minor bump) all pass.

…b-tracking groundwork

- fix pre-existing biome lint errors (4 errors across app + package)
- add first test suite: 75 tests over .lab parsing, parameter schema,
  timeline evaluation, composition math, blob tracker, inner effects
- CI now lints, typechecks and tests the editor app, not just the package
- .lab import: zod schema validation, consent prompt before imported
  custom-shader code runs, SVG raster resolution capped at 8192
- lazy-load export dialog and video muxers (-99.9 KB first-load JS)
- close the video encoder on failed/cancelled exports; 30s timeout on
  stalled video texture loads
- onRuntimeError no longer fires with null after successful init
- renderer dedup: drift inventory + consolidation design (plans/006-artifacts)
- drop localeCompare from per-frame parameter signatures
- blob-tracking foundation: pure CPU tracker + inner-effects modules (unwired)

Includes patch changesets for the two package changes.
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shader-lab Ready Ready Preview, Comment Jul 7, 2026 4:00pm

git-chad added 2 commits July 7, 2026 12:17
…, decorations)

Wires the blob-tracking layer into the editor end to end:

- BlobTrackingPass: 64x36 motion+luminance analysis with previous-frame
  feedback, non-blocking readRenderTargetPixelsAsync readback (live mode
  consumes last frame's buffer, never awaits), CPU tracker integration,
  32-blob DataTexture table, aspect-correct square/circle/diamond SDF
  composite with shapeScale/invert, decorated and mask output modes
  (mask = white fills on black for the existing compositeMode machinery),
  CCTV decoration overlay (outlines, id+coordinate labels, straight or
  curved connecting lines, decaying trails) drawn on a CPU canvas and
  alpha-composited — never present in mask output, rewind reset, and a
  prepareForExportFrame that awaits the readback and steps the tracker
  once per distinct timestamp for deterministic exports
- single inner-effect child pass (own switch over the 21 pass-backed
  effect types; no factory import to avoid a cycle) rendering into a
  private half-float target sampled inside shapes; child lifecycle
  (dispose on type change, size forwarding, param application through
  the tolerant JSON parser)
- registration: EFFECT_LAYER_TYPES, layer registry params (Detection /
  Shapes / Inner Effect / Decorations groups; innerEffectParams hidden
  via the custom-shader sentinel pattern), pass factory, layer picker
  entry, shader-export unsupported list
- properties sidebar: BlobInnerEffectSection renders the chosen inner
  effect's parameters against the hidden JSON param with visibleWhen
  support and no keyframe affordances (not keyframeable in v1)
- inner-effect set now excludes blob-tracking itself (no recursive
  children) with a regression test
Package half of the blob-tracking feature:

- blob-tracking-tracker.ts: verbatim copy of the editor's pure CPU
  tracker (self-contained module, no imports)
- blob-tracking-inner-effects.ts: package flavor of the inner-effect
  set and tolerant JSON param parsing; no registry defaults — package
  passes apply their own per-parameter fallbacks in updateParams
- blob-tracking-pass.ts: mirror of the editor pass adapted to the
  package runtime (tracker steps on the runtime clock's render time,
  no export-frame hook, createPipelinePlaceholder for half-float
  placeholders, decorations degrade to nothing without document)
- registered in ShaderLabEffectLayerType, the pipeline's LayerPassNode
  union and createPass switch
- README supported-layers list + inner-effect config docs in both
  READMEs; ShaderLabBlobInnerEffect helper type exported from index
- minor changeset
@git-chad git-chad changed the title Editor hardening, test baseline, CI validation, export fixes, and blob-tracking groundwork Editor hardening, test baseline, CI validation, export fixes, and the blob-tracking layer Jul 7, 2026
Busy video content made every frame change the tracker state, which
paid a full decoration-canvas redraw plus a full-resolution
CanvasTexture re-upload (~8 MB/frame at 1080p) every frame — the
webcam case felt fine only because quasi-static scenes rarely
invalidated the overlay signature. Detection itself is fixed-cost
(64x36 grid, 32-blob cap) and unaffected.

- overlay canvas resolution capped at 960px wide (linear upscale;
  stroke widths and label sizes compensated so visuals are unchanged)
- change signature quantized to overlay pixels, so sub-pixel jitter
  no longer counts as a change
- live redraws rate-limited to ~30 Hz; the signature stays stale on
  skipped frames so the next eligible frame catches up; export frames
  bypass the throttle (prepareForExportFrame forces the redraw) to
  keep exports deterministic
- trails draw every other history entry (visually equivalent, half
  the strokes)

Applied identically to the editor pass and the package mirror.
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