Red, green and blue lights cast crisp, colored shadows through spinning shapes.
For each light, rays are cast toward every corner of every wall and shape, plus a hair to either side. The nearest hit for each ray, sorted by angle, outlines a visibility polygon: everything that light can see. Filling those polygons with radial gradients in additive mode lets colored lights mix where they overlap.
Try it. Move the pointer to carry a light. Click to drop it and pick up another.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a 2D lighting demo with colored lights and crisp shadows using JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Make a canvas that fills the window and resizes with it, with a dark background.
- Place about 12 slowly rotating polygons (triangles, squares, hexagons) around the room. Each frame, turn their edges plus the four walls of the window into a list of line segments.
- For a light at the pointer, compute its visibility polygon: for every segment endpoint, cast three rays from the light, one straight at it and two offset by about 0.0001 radians. Use ray versus segment intersection to find the nearest hit for each ray, sort the hits by angle, and connect them into a polygon.
- Fill that polygon with a radial gradient centered on the light that fades to transparent, then draw the shapes in near-black on top.
Once that works, make it beautiful:
- Use three lights, red, green and blue, and draw their polygons with globalCompositeOperation = "lighter" so they add up to white where they overlap and leave colored shadows where only some of them reach.
- Draw the lights into an offscreen light map, then multiply it over a subtle tiled floor so the light seems to land on a surface.
- Light the edges of each shape that face a light in that light's color, and draw each light as a small glowing orb.
- Let the lights wander when idle; the pointer carries one, and a click drops it and picks up another.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as soft shadows from several samples per light, a small top-down game with line of sight, or mirrors that reflect the rays.