Skip to content

feat: parametric shadows (coverage-contour, pixel style, point lights, animated, React/Vue)#72

Merged
apresmoi merged 16 commits into
mainfrom
feat/parametric-shadows
Jun 21, 2026
Merged

feat: parametric shadows (coverage-contour, pixel style, point lights, animated, React/Vue)#72
apresmoi merged 16 commits into
mainfrom
feat/parametric-shadows

Conversation

@apresmoi

Copy link
Copy Markdown
Collaborator

Parametric shadows

A lightweight, opt-in shadow path (shadow.parametric) that replaces a caster's per-polygon/silhouette projection with low-resolution coverage-contour loops — far fewer DOM/SVG vertices, cheaper projection. The exact path stays the default and is unchanged.

Quality (rubric-driven)

The approximation is governed by named, measurable rubrics (bench/shadow-rubric.mjs, parametric-vs-exact pixel diff). Correction terms:

  • flat casters → exact path (a tilted proxy would project garbage onto a coplanar receiver)
  • convex casters skip self-shadow (a convex surface self-shadows nothing)
  • self-shadow depth-bias (flat band proxies otherwise over-darken)
  • hole subtraction (courtyards / the coliseum arena trace as opposite-wound loops and subtract under fill-rule: nonzero)

Features

  • shadow.definition — detail knob (silhouette points / pixel-grid resolution); per-mesh override via PolyMeshTransform.shadowDefinition (vanilla), <PolyMesh shadowDefinition> (React), shadow-definition (Vue).
  • shadow.style: "vector" | "pixel" — smooth contour or greedy-meshed voxel blocks (holes free as absent cells).
  • Point lights — each shadow-casting point light gets its own radial silhouette (the directional outline is wrong for a finite light).
  • shadow.dragDefinition (vanilla) — progressive refinement: low def during a light drag, debounced full-def refine at rest (laggless; ~100fps on the castle vs 36fps full).
  • shadow.followAnimation (all three) — shadows track a deforming/animated mesh; frozen by default (re-emitting per frame is expensive), opt-in, throttled.

Cross-package

The override builder (buildParametricCasterOverride + isFlatCaster/isConvexCaster) lives in core, so vanilla / React / Vue produce byte-identical loops. Only intentional asymmetry: progressive dragDefinition is a vanilla scene-orchestration concern (React/Vue do it idiomatically via app state).

Website

Gallery + Builder expose Parametric / Shadow def. / Pixel / Animate-shadow controls in the Lighting panel. Gallery defaults to parametric (def 35, vector) with animated shadows on.

Tooling

bench/shadow-rubric.mjs (rubric scorer), bench/shadow-diff.mjs (parametric-vs-exact), bench/shadow-trace.html + chrome-trace (perf).

All tests + pnpm build + pnpm build:website green; 14/14 rubrics.

apresmoi added 16 commits June 21, 2026 06:59
@apresmoi apresmoi merged commit b84e15d into main Jun 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant