Follow-up to #4: 2D lighting tiers 3-4 + Light2D/Occluder as ECS components #47
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#47
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #4, which shipped the light-accumulation core in
a71279a: theLight.*namespace —Light.ambient(scene modulate),Light.point(additive radial glow, linear falloff), andLight.occlude/Light.clear_occluders(hard shadows). That is the imperative escape hatch the proposal named, covering tiers 1 (ambient + additive radial lights) and 2 (hard shadows).This tracks the remaining tiers and the ECS-native shape:
Light2D/Occluderconsumed automatically by a built-in Render phase (draw scene → multiply by ambient → accumulate eachLight2D→ carveOccludershadows), so a torch is just an entity carryingPosition + Light2D. This needs an engine-owned system over user components — the same ECS hook #43 is blocked on; do it once and both features land.Light.time_of_day(t)animating ambient + aDirectionalLight2D-style global light).falloffexponent) and a spot/cone light.Related: #4 (the shipped core), #43 (the engine-owned-system hook the ECS-component layer needs).
Shipped the ECS-native shape — the checkbox this issue named as needing "an engine-owned system over user components" — in
3679ce1, on the hook landed in #43.A torch is now just an entity carrying
Light2D { x, y, radius, color, intensity }, a wall an entity carryingOccluder { x, y, w, h }, and oneAmbient { color }entity sets the night tint. The engine runs the whole light pass at the end of the Render phase — ambient modulate → carve occluder shadows → accumulate each additive radialLight2D→ present — with noLight.*calls wired. It reuses the deterministic accumulation core from #4 (light_ambient/light_occlude/light_point) but consumes components through the by-name reflection ABI instead of imperative calls. ALight2D/Occluderreads its position from aPosition { x, y }component when the entity carries one, else its ownx/y, so "Position + Light2D" and a self-positioned light both work.Runtime in
runtime/native/systems_light.ludic(split from the animation systems so a game without lights never links the light pass). Documented under Engine-owned systems in LANGUAGE.md.Proof.
examples/library/light_ecs.ludicdraws a white scene, spawns Ambient/Light2D/Occluder entities, drives onetick_render, and samples the framebuffer withScreen.pixel: ambient-only corner = 32, torch centre lit, a point the pillar shadows = 32 (ambient), an unblocked equidistant point lit →32 1 32 1, now in the regression suite (74 passed, self-host fixpoint intact, no golden drift).The remaining render-quality tiers — normal-mapped sprites (tier 3), soft shadows/penumbra, spot/cone lights, falloff-curve options, cookies and a day/night helper (tier 4) — extend the accumulation core and need no further ECS plumbing; tracked in #49. Colored lights already work (per-
Light2Dcolor). Closing as the ECS-native shape is delivered.