What this tool does
The Raycast Visualizer is an interactive demo of 2D visibility-polygon computation, the algorithm behind line-of-sight in stealth games, light propagation in 2D engines, and "what can a guard see from this corner" puzzles. Move the pointer over the canvas and the tool casts rays from that point, finds where each one first hits a wall, and fills the polygon of everything visible.
It's not a finished engine; it's a teaching surface. Three preset scenes (rooms, pillars, diagonals) exercise different geometric edge cases.
How the algorithm works
For every line-segment wall in the scene:
1. Cast a ray from the light toward each wall's two endpoints. That alone gives you the silhouette of obstacles. 2. Cast ±epsilon extra rays on each side of every endpoint. This is the trick, without the spread, the ray exactly hits the corner and the polygon would have nothing to wrap around the wall behind it. The two extra rays "peek around the corner" and continue until they hit the next wall. 3. Optionally cast N fill rays at evenly spaced angles. These don't change correctness, the endpoint rays already define the polygon, but they give the polygon-fill mode smoother edges in render mode. 4. Sort all hits by angle around the light, and you have the visibility polygon as a closed loop.
The whole computation is O((W + F) · W) per frame where W is wall count and F is fill rays. For the built-in scenes that's a few hundred segment intersections per pointer move, trivial on any modern machine.
Reading the canvas
- Light source, the small dot at the pointer position.
- Walls, black line segments. Toggle visibility with the "Show walls" switch.
- Polygon mode, the visible region is filled with a radial gradient from light to dark. This is the gameplay-style render.
- Ray-line mode, every cast ray is drawn as a faint line. This is the debug-style render that makes the algorithm legible.
- Stats overlay, top-right corner shows ray count, frame milliseconds, and FPS. Watch how the numbers move when you change the fill-ray count.
The three preset scenes
- Rooms, two adjacent rooms with doorways. Exercises the standard "look through an opening" case.
- Pillars, a regular grid of small obstacles. Stresses the algorithm with many short walls and many corners.
- Diagonals, a sparse set of non-axis-aligned walls. Makes diagonal-corner peek artefacts obvious if your epsilon spread is too tight.
Reduced-motion mode
If your OS has prefers-reduced-motion: reduce set, the visualizer switches to snapshot mode, it draws the polygon only when the pointer moves, not in a continuous animation loop. The algorithm is identical; only the render schedule changes. The "Reduced motion" badge appears at the top so you know it's active.
Common questions about the math
- Why epsilon rays and not exact endpoint rays? An exact endpoint ray ends at the corner. The polygon vertex is at that exact point, and the polygon would have no width to wrap around the wall extending past the corner. Two ε-offset rays continue past the corner into the next gap, giving the polygon two extra vertices to wrap around.
- What happens with overlapping walls? Each ray reports its closest hit, so an inner wall always occludes a wall behind it. There's no Z-buffering needed, line-segment intersection naturally ranks by
t. - Why doesn't the polygon close cleanly sometimes? If your fill-ray count is 0 and the scene has very long walls between adjacent corners, the polygon edge between two endpoint hits is a straight line, fine for short walls, visibly faceted for long ones. Increase fill rays to smooth.
Privacy
Everything, the scene data, the math, the rendering, runs in your browser on a <canvas>. There are no network requests during interaction. The PNG export is a local canvas.toBlob download. No data leaves the page.