From 7ed5ab74ffc61512195fdde5c5314badde9e12cc Mon Sep 17 00:00:00 2001 From: Juan Cruz Fortunatti Date: Sun, 21 Jun 2026 19:03:54 +0200 Subject: [PATCH] docs: document parametric shadows (definition, style, point lights, dragDefinition, followAnimation) --- .../content/docs/components/poly-scene.mdx | 3 ++- website/src/content/docs/guides/lighting.mdx | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/website/src/content/docs/components/poly-scene.mdx b/website/src/content/docs/components/poly-scene.mdx index 02ae7f2e..6059ec6e 100644 --- a/website/src/content/docs/components/poly-scene.mdx +++ b/website/src/content/docs/components/poly-scene.mdx @@ -26,7 +26,7 @@ The React/Vue components and `createPolyScene()` support the full table. The `

` atlas slices; `` cannot be disabled. | | `autoCenter` | `boolean` | `false` | Rotate around the content bbox center instead of world origin. Polygon data is not mutated. | | `centerPolygons` | `Polygon[]` | None | (Framework only.) Bbox source for `autoCenter` when renderable polygons live inside child meshes. | -| `shadow` | `{ color?, opacity?, lift?, maxExtend? }` | `{ color:"#000000", opacity:0.25, lift:0.05, maxExtend:2000 }` | Appearance and SVG extent cap for cast shadows emitted by meshes with `castShadow`. | +| `shadow` | `{ color?, opacity?, lift?, maxExtend?, parametric?, definition?, style?, dragDefinition?, followAnimation? }` | `{ color:"#000000", opacity:0.25, lift:0.05, maxExtend:2000 }` | Appearance + SVG extent cap for cast shadows. `parametric` swaps to a cheap low-res silhouette (`definition` = detail, `style: "vector" \| "pixel"`); `dragDefinition` (vanilla) and `followAnimation` cover light-drag and animated meshes. See [Parametric shadows](/guides/lighting/#parametric-shadows). | | `polygons` | `Polygon[]` | None | (Framework only.) Flat array of polygon objects rendered as direct children. Composes with JSX/slot children. | | `children` | None | None | Meshes, polygons, controls, helpers, selection wrappers, and transform controls. | @@ -54,6 +54,7 @@ React/Vue `` supports the full table. The `` custom element | `parseOptions` | `UseMeshOptions` | Parser options forwarded to `loadMesh`; `meshResolution` defaults to `"lossy"`. | | `meshResolution` | `"lossless" \| "lossy"` | Top-level optimizer intent. Wins over `parseOptions.meshResolution`; defaults to `"lossy"`. | | `castShadow` | `boolean` | Emit SVG cast shadows in both lighting modes; projections update when light, ground, or mesh geometry changes. | +| `shadowDefinition` | `number` | Per-mesh parametric-shadow detail, overriding the scene's `shadow.definition` (only when `shadow.parametric`). | | `fallback` | `ReactNode` | Rendered while `src` is loading. (React / Vue only.) | | `errorFallback` | `(error: Error) => ReactNode` | Rendered if parse fails. (React / Vue only.) | | `children` | `(polygon, index) => ReactNode` | Per-polygon render prop / scoped slot. (React / Vue only.) | diff --git a/website/src/content/docs/guides/lighting.mdx b/website/src/content/docs/guides/lighting.mdx index 29f386ab..8abffd4f 100644 --- a/website/src/content/docs/guides/lighting.mdx +++ b/website/src/content/docs/guides/lighting.mdx @@ -175,6 +175,31 @@ What to expect: - **Colored multi-light shadows.** Each light's shadow is filled with the receiver lit by every *other* light, so a spot blocked from one colored light still shows the others' color. Where two shadows overlap, the region composites to the both-blocked color (ambient only) — not a doubled-up black smear. - **`shadow.lift`** floats the shadow a hair above the receiver to avoid z-fighting; the default is fine, just don't set it to exactly `0` on a coplanar floor. +## Parametric shadows + +By default a shadow projects every casting polygon. Set `shadow: { parametric: true }` and PolyCSS instead casts one low-resolution **coverage silhouette** per caster — far fewer DOM/SVG vertices and a cheaper projection, at the cost of an approximate (but concave- and hole-aware) outline. The exact path stays the default; parametric is purely opt-in and works in all three renderers. + +```js +// vanilla +scene.setOptions({ shadow: { parametric: true, definition: 32 } }); +``` + +```jsx +// React + +``` + +```vue + + +``` + +- **`definition`** (default `16`) — silhouette detail. Higher → closer to the exact outline and sharper holes, but more vertices. Override it per mesh with **`shadowDefinition`** (`PolyMeshTransform.shadowDefinition` in vanilla, `` in React, `shadow-definition` in Vue) so a detailed hero caster stays crisp while simple props run cheap in the same scene. +- **`style: "vector" | "pixel"`** — `"vector"` (default) traces a smooth concave contour; `"pixel"` greedy-meshes the coverage into blocky **voxel** rectangles, where `definition` becomes the pixel-grid resolution (lower → chunkier). Holes (courtyards, an arena) come through in both. +- **Point lights** are supported — each casting point light gets its own radial silhouette. +- **`dragDefinition`** *(vanilla `createPolyScene` only)* — progressive refinement. While the directional light is being dragged the shadow renders at this lower definition for a smooth drag, then a debounced pass re-emits at full `definition` once the light settles. React/Vue get the same effect by lowering `definition` in component state during a drag. +- **`followAnimation`** — by default a deforming/animated caster's shadow **freezes** at the last pose (re-projecting it every frame is expensive). Set `followAnimation: true` to make the shadow track the animation; pair it with `parametric` + a modest `definition` so the per-frame reprojection stays cheap. + ## Live & animated lights - **Animating the directional light:** use **dynamic** mode — moving the light is a single CSS-variable write per frame, no JS in the paint loop, and shadows re-project automatically.