feat(light): render-quality tiers 3-4 — cones, falloff, soft shadows, gels, normals, day/night (#49)
The remaining lighting tiers from the original proposal, all extending the deterministic accumulation core (light.ludic) — no new ECS plumbing: - Light.spot: cone / flashlight lights (direction + spread degrees), with a self-contained integer atan2-in-degrees and a feathered edge. - Light.falloff: a brightness-ramp exponent (1 linear, 2 quadratic, …) via repeated fixed multiply. - Light.soft: soft shadows — an area-sampled light so an occluder edge fades through a penumbra instead of a hard cut. - Light.gel + Light.clear_gel: colour cookies — a light gels from its centre colour to a rim colour. - Light.normal + Light.clear_normals + Light.height: a normal G-buffer so surfaces shade by facing (N·L), not distance alone (tier 3). - Light.time_of_day: a day/night ambient ramp from a single 0..1 value. The engine lighting system (systems_light.ludic) consumes matching optional Light2D fields — direction/spread/falloff/softness/gel — each defaulting off so an older five-field Light2D lights exactly as before. Every tier is integer + Q16.16 fixed, so scenes light identically on every run and headless. Worked example + regression: examples/library/light_tiers.ludic (1 1 1 1 1 1 1 1 1). Nine new docs/language/light pages. Full suite 76 passed, self-host C-free fixpoint intact, no golden drift. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
377b6d1186
commit
382826889f
18 changed files with 7752 additions and 6502 deletions
|
|
@ -270,7 +270,7 @@ enough, and a game that declares none is byte-for-byte unchanged.
|
|||
|---|---|---|
|
||||
| `SpriteAnim { ticks, fps, frames, mode, frame }` | `Update` | advances `frame` — spritesheet frame animation (`mode` 0 loop, 1 once, 2 ping-pong) |
|
||||
| `Motion { ticks, dur, from, to, ease, value, done }` | `Update` | advances `value` — value tween (`ease` 0 linear, 1 in, 2 out, 3 in-out), latches `done` |
|
||||
| `Light2D { x, y, radius, color, intensity }` | `Render` | additive radial glow; the engine runs the whole 2D light pass and presents |
|
||||
| `Light2D { x, y, radius, color, intensity }` | `Render` | additive radial glow; the engine runs the whole 2D light pass and presents. Optional `direction`/`spread` (cone), `falloff`, `softness`, `gel` fields select the render-quality tiers |
|
||||
| `Occluder { x, y, w, h }` | `Render` | a rectangular shadow caster the light pass carves out |
|
||||
| `Ambient { color }` | `Render` | one entity tints the whole scene (night/cave) before lights accumulate |
|
||||
|
||||
|
|
@ -286,7 +286,11 @@ A `Light2D` / `Occluder` reads its position from a `Position { x, y }` component
|
|||
on the same entity when the entity carries one, else from its own `x` / `y`
|
||||
fields — so "Position + Light2D" and a self-positioned light both work. With
|
||||
`Light2D` present the engine owns the frame flip: a draw handler renders the
|
||||
scene and does **not** call `Screen.show`.
|
||||
scene and does **not** call `Screen.show`. Beyond the radial core the light pass
|
||||
carries the render-quality tiers — `Light.spot` cones, a `Light.falloff`
|
||||
exponent, `Light.soft` shadows (penumbra), `Light.gel` colour cookies,
|
||||
normal-mapped surfaces (`Light.normal` + `Light.height`), and a
|
||||
`Light.time_of_day` day/night ramp — every one deterministic.
|
||||
|
||||
### Input actions & deterministic replay
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue