Lighter
A Löve light/shadow library
Install / Use
/learn @speakk/LighterREADME
Lighter
A dynamic light / shadow casting library for Löve.
Installation
Clone the repo into your libs directory and require with
require 'path.to.lighter'
Usage
local Lighter = require 'path.to.lighter'
local lighter = Lighter()
local wall = {
100, 100,
300, 100,
300, 300,
100, 300
}
lighter:addPolygon(wall)
local lightX, lightY = 500, 500
-- addLight signature: (x,y,radius,r,g,b,a)
local light = lighter:addLight(lightX, lightY, 500, 1, 0.5, 0.5)
function love.update(dt)
lightX, lightY = love.mouse.getPosition()
lighter:updateLight(light, lightX, lightY)
end
function love.draw()
love.graphics.polygon('fill', wall)
lighter:drawLights()
end
-- Clean up
-- lighter:removeLight(light)
-- lighter:removePolygon(wall)
How to use in your game context with a darker global illumination:
(remember you can use any combination of additive & multiplicative blending to achieve a result you like)
-- Call after your light positions have been updated
function preDrawLights()
love.graphics.setCanvas({ lightCanvas, stencil = true})
love.graphics.clear(0.4, 0.4, 0.4) -- Global illumination level
self.lighter:drawLights()
love.graphics.setCanvas()
end
-- Call after you have drawn your scene (but before UI)
function drawLights()
love.graphics.setBlendMode("multiply", "premultiplied")
love.graphics.draw(lightCanvas)
love.graphics.setBlendMode("alpha")
end
Function signatures of the public API:
init = function(self, options)
addLight = function(self, x, y, radius, r, g, b, a, gradientImage)
updateLight = function(self, light, x, y, radius, r, g, b, a, gradientImage)
removeLight = function(self, light)
addPolygon = function(self, polygon)
removePolygon = function(self, polygon)
drawVisibilityPolygon = function(self, light)
drawLights = function(self)
Credits:
- Helped me understand the premise and their code provided me with tons of helpful tips for getting this implemented: https://github.com/OneLoneCoder
- The actual page I ended up following to really get the idea: https://ncase.me/sight-and-light/
Screenshot of the library in use in a game

How it works under the hood
For each light we cast rays towards wall polygon corners (aka map features). Checks intersections. Builds a visibility polygon and uses it as the stencil for drawing the light.
As an optimization it uses a spatial map and calculates polygon bounding boxes on the fly so that only polygons within light radius get included in the visibility polygon calculations.
Related Skills
node-connect
335.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
335.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
82.7kCommit, push, and open a PR
