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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant