A software light pass over the framebuffer, run in a render phase after drawing the scene: Light.ambient multiplies the scene toward a tint (night/cave mood), Light.point additively accumulates a radial glow with linear falloff clamped per channel, and Light.occlude / Light.clear_occluders cast hard shadows by blocking a light's rays against rectangular occluders. Integer + Q16.16 fixed throughout, so a scene lights identically every run and in a headless render (diffable). Engine in runtime/native/light.ludic, spliced on demand (g_uses_light) like the regex/query runtimes; namespace wired in emit_call.ludic. Ships issue #4 tiers 1 (ambient + additive radial lights) and 2 (hard shadows). Normal-mapped sprites, soft shadows, a day/night directional light, and auto-consuming Light2D/Occluder components are follow-ups (the auto-system hook is tracked by #43). - runtime/native/light.ludic: the light-accumulation engine (isqrt falloff, segment/occluder shadow test, ambient modulate) - examples/library/lighting.ludic: 14 pixel-readback assertions - docs/language/light/: Light.ambient/point/occlude/clear_occluders - tools/x/test.ludic: lighting.ludic in the regression suite Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1.4 KiB
1.4 KiB
| id | name | category | kind | tokens | sig | tip | order | ns | member |
|---|---|---|---|---|---|---|---|---|---|
| light-point | Light.point | light | namespace-method | Light.point | Light.point(x, y, radius, color, energy) | Add a radial glow that falls off with distance. | 2 | Light | point |
Additively accumulates a radial point light centred at (x, y). Brightness is full at the centre and falls off linearly to zero at radius pixels, scaled by energy (a fixed multiplier — 1.0 is full, 2.0 over-drives toward white, 0.5 is dim), and clamped per channel at 255 so overlapping lights add without wrapping. Only the light's bounding box is touched, and any Light.occlude rectangle between the centre and a pixel puts that pixel in shadow. Colours are 0x00RRGGBB.
Parameters:
x,y— the light centre, in screen pixelsradius— the reach in pixels; brightness is zero at and beyond itcolor— the light colour,0x00RRGGBBenergy— afixedbrightness multiplier (1.0= full)
program Demo {
property Torch { x: int = 0, y: int = 0 }
model Lamp { Torch }
handler Render phase Update {
Screen.clear(0)
Light.ambient(Color.rgb(32, 32, 48))
Light.point(80, 60, 70, Color.rgb(255, 210, 130), 1.0) # a warm torch
Screen.show()
}
}