Follow-up to #47: lighting tiers 3-4 — normal maps, soft shadows, spot/cone, falloff curves, day/night #49
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#49
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 #47, which shipped the ECS-native shape the lighting proposal named as the headline — the item blocked on "an engine-owned system over user components" (
3679ce1). A torch is now just an entity carryingLight2D { 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 deterministic light pass at the end of the Render phase (ambient modulate → carve occluder shadows → accumulate each additive radial light) and presents, with noLight.*calls wired. Positions come from aPositioncomponent when present, else the light's own x/y. Colored lights already work (per-Light2Dcolor). Seeruntime/native/systems_light.ludicandexamples/library/light_ecs.ludic.This tracks the remaining render-quality tiers from the original proposal, none of which need new ECS plumbing — they extend the accumulation core (
runtime/native/light.ludic):Light2Dshades surfaces by angle, not just distance.Light2Dvariant (addangle+spreadfields, consumed by the same system).falloffexponent onLight2D(today falloff is linear).Light.time_of_day(t)animating ambient + a global directional light).Related: #4 (the accumulation core), #47 (the shipped ECS-native shape), #43 (the engine-owned-system hook both consume).
Shipped in
3828268(feat(light): render-quality tiers 3-4, #49). All tiers extend the deterministic accumulation core (runtime/native/light.ludic) — no new ECS plumbing — and every one is integer + Q16.16 fixed, so scenes light identically on every run and headless.Light.normal(x, y, w, h, nx, ny)stamps a per-pixel surface normal into a G-buffer parallel to the framebuffer, and each light shades those pixels byN·L(facing), not distance alone.Light.height(h)sets the light's virtual z;Light.clear_normals()resets each frame. Unstamped pixels are unaffected (factor 1), so a scene with no normals lights exactly as before.Light.soft(radius)treats the light as a small disk and averages visibility from a cross of sample points, so anOccluderedge fades through a penumbra instead of a hard cut.Light.soft(0)restores hard shadows.Light.spot(x, y, radius, color, energy, direction, spread)— a directional wedge (degrees), with a self-contained integer atan2-in-degrees (no trig prelude pulled in) and a feathered edge.Light.falloff(exponent)raises the brightness ramp to an integer power (1 linear, 2 quadratic, …) via repeated fixed multiply.Light.gel(color)/Light.clear_gel()give a colour cookie (the light gels centre → rim), andLight.time_of_day(t)ramps a deep-blue night up to full daylight and back from a single 0..1 value.The engine lighting system (
systems_light.ludic) consumes matching optionalLight2Dfields —direction/spread/falloff/softness/gel— each defaulting off, so an older five-fieldLight2Dis unchanged.Worked example + regression:
examples/library/light_tiers.ludic(1 1 1 1 1 1 1 1 1, verified by pixel readback). Nine newdocs/language/lightpages. Full suite 76 passed, self-host C-free fixpoint intact, no golden drift.