mirror of
https://github.com/tanema/light_world.lua.git
synced 2024-12-24 20:24:19 +00:00
Init project
This commit is contained in:
commit
d1b1b3e0fa
35
conf.lua
Normal file
35
conf.lua
Normal file
@ -0,0 +1,35 @@
|
||||
function love.conf(t)
|
||||
t.identity = nil -- The name of the save directory (string)
|
||||
t.version = "0.9.0" -- The LÖVE version this game was made for (string)
|
||||
t.console = true -- Attach a console (boolean, Windows only)
|
||||
|
||||
t.window.title = "Untitled" -- The window title (string)
|
||||
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
||||
t.window.width = 800 -- The window width (number)
|
||||
t.window.height = 600 -- The window height (number)
|
||||
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
||||
t.window.resizable = false -- Let the window be user-resizable (boolean)
|
||||
t.window.minwidth = 1 -- Minimum window width if the window is resizable (number)
|
||||
t.window.minheight = 1 -- Minimum window height if the window is resizable (number)
|
||||
t.window.fullscreen = false -- Enable fullscreen (boolean)
|
||||
t.window.fullscreentype = "normal" -- Standard fullscreen or desktop fullscreen mode (string)
|
||||
t.window.vsync = false -- Enable vertical sync (boolean)
|
||||
t.window.fsaa = 0 -- The number of samples to use with multi-sampled antialiasing (number)
|
||||
t.window.display = 1 -- Index of the monitor to show the window in (number)
|
||||
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean). Added in 0.9.1
|
||||
t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean). Added in 0.9.1
|
||||
|
||||
t.modules.audio = true -- Enable the audio module (boolean)
|
||||
t.modules.event = true -- Enable the event module (boolean)
|
||||
t.modules.graphics = true -- Enable the graphics module (boolean)
|
||||
t.modules.image = true -- Enable the image module (boolean)
|
||||
t.modules.joystick = true -- Enable the joystick module (boolean)
|
||||
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
||||
t.modules.math = true -- Enable the math module (boolean)
|
||||
t.modules.mouse = true -- Enable the mouse module (boolean)
|
||||
t.modules.physics = true -- Enable the physics module (boolean)
|
||||
t.modules.sound = true -- Enable the sound module (boolean)
|
||||
t.modules.system = true -- Enable the system module (boolean)
|
||||
t.modules.timer = true -- Enable the timer module (boolean)
|
||||
t.modules.window = true -- Enable the window module (boolean)
|
||||
end
|
557
light.lua
Normal file
557
light.lua
Normal file
@ -0,0 +1,557 @@
|
||||
LOVE_LIGHT_CURRENT = nil
|
||||
LOVE_LIGHT_CIRCLE = nil
|
||||
LOVE_LIGHT_POLY = nil
|
||||
LOVE_LIGHT_LAST_BUFFER = nil
|
||||
|
||||
LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl")
|
||||
LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl")
|
||||
|
||||
love.light = {}
|
||||
|
||||
-- light world
|
||||
function love.light.newWorld()
|
||||
local o = {}
|
||||
o.lights = {}
|
||||
o.ambient = {0, 0, 0}
|
||||
o.poly = {}
|
||||
o.circle = {}
|
||||
o.shadow = love.graphics.newCanvas()
|
||||
o.shine = love.graphics.newCanvas()
|
||||
o.shader = love.graphics.newShader("shader/light.glsl")
|
||||
o.changed = true
|
||||
o.blur = true
|
||||
-- update
|
||||
o.update = function()
|
||||
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
|
||||
love.graphics.setShader(o.shader)
|
||||
if o.changed then
|
||||
love.graphics.setCanvas(o.shadow)
|
||||
o.shadow:clear(unpack(o.ambient))
|
||||
love.graphics.setBlendMode("additive")
|
||||
else
|
||||
love.graphics.setColor(255,255,255)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
end
|
||||
|
||||
local lightsOnScreen = 0
|
||||
LOVE_LIGHT_POLY = o.poly
|
||||
LOVE_LIGHT_CIRCLE = o.circle
|
||||
for i = 1, #o.lights do
|
||||
if o.lights[i].changed or o.changed then
|
||||
local curLightX = o.lights[i].x
|
||||
local curLightY = o.lights[i].y
|
||||
local curLightRange = o.lights[i].range
|
||||
local curLightColor = {
|
||||
o.lights[i].red / 255.0,
|
||||
o.lights[i].green / 255.0,
|
||||
o.lights[i].blue / 255.0
|
||||
}
|
||||
local curLightSmooth = o.lights[i].smooth
|
||||
local curLightGlow = {
|
||||
1.0 - o.lights[i].glowSize,
|
||||
o.lights[i].glowStrength
|
||||
}
|
||||
|
||||
if curLightX+curLightRange > 0 and curLightX-curLightRange < love.graphics.getWidth()
|
||||
and curLightY+curLightRange > 0 and curLightY-curLightRange < love.graphics.getHeight()
|
||||
then
|
||||
local lightposrange = {curLightX, love.graphics.getHeight() - curLightY, curLightRange}
|
||||
LOVE_LIGHT_CURRENT = o.lights[i]
|
||||
o.shader:send("lightPositionRange", lightposrange)
|
||||
o.shader:send("lightColor", curLightColor)
|
||||
o.shader:send("smooth", curLightSmooth)
|
||||
o.shader:send("glow", curLightGlow)
|
||||
|
||||
if o.changed then
|
||||
love.graphics.setCanvas(o.shadow)
|
||||
else
|
||||
love.graphics.setCanvas(o.lights[i].shadow)
|
||||
love.graphics.clear()
|
||||
end
|
||||
|
||||
-- draw shadow
|
||||
love.graphics.setInvertedStencil(shadowStencil)
|
||||
love.graphics.setBlendMode("additive")
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
-- draw shine
|
||||
love.graphics.setCanvas(o.lights[i].shine)
|
||||
o.lights[i].shine:clear(255, 255, 255)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setStencil(polyStencil)
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
lightsOnScreen = lightsOnScreen + 1
|
||||
end
|
||||
|
||||
o.lights[i].changed = o.changed
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setShader()
|
||||
if not o.changed then
|
||||
love.graphics.setCanvas(o.shadow)
|
||||
love.graphics.setStencil()
|
||||
love.graphics.setColor(unpack(o.ambient))
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.setBlendMode("additive")
|
||||
for i = 1, #o.lights do
|
||||
love.graphics.draw(o.lights[i].shadow)
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setCanvas(o.shine)
|
||||
love.graphics.setColor(0,0,0)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
love.graphics.setColor(255,255,255)
|
||||
love.graphics.setBlendMode("additive")
|
||||
for i = 1, #o.lights do
|
||||
love.graphics.draw(o.lights[i].shine)
|
||||
end
|
||||
|
||||
love.graphics.setShader()
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setStencil()
|
||||
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
|
||||
|
||||
o.changed = false
|
||||
end
|
||||
-- draw shadow
|
||||
o.drawShadow = function()
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
if o.blur then
|
||||
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setCanvas(o.shadow)
|
||||
love.graphics.setShader(LOVE_LIGHT_BLURV)
|
||||
love.graphics.draw(o.shadow)
|
||||
love.graphics.setShader(LOVE_LIGHT_BLURH)
|
||||
love.graphics.draw(o.shadow)
|
||||
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
|
||||
love.graphics.setBlendMode("multiplicative")
|
||||
love.graphics.setShader()
|
||||
love.graphics.draw(o.shadow)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
else
|
||||
love.graphics.setBlendMode("multiplicative")
|
||||
love.graphics.setShader()
|
||||
love.graphics.draw(o.shadow)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
end
|
||||
end
|
||||
|
||||
-- draw shine
|
||||
o.drawShine = function()
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.setBlendMode("multiplicative")
|
||||
love.graphics.setShader()
|
||||
love.graphics.draw(o.shine)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
end
|
||||
-- new light
|
||||
o.newLight = function(x, y, red, green, blue, range)
|
||||
o.lights[#o.lights + 1] = love.light.newLight(o, x, y, red, green, blue, range)
|
||||
|
||||
return o.lights[#o.lights]
|
||||
end
|
||||
-- clear lights
|
||||
o.clearLights = function()
|
||||
o.lights = {}
|
||||
end
|
||||
-- clear objects
|
||||
o.clearObjects = function()
|
||||
o.poly = {}
|
||||
o.circle = {}
|
||||
end
|
||||
-- set ambient color
|
||||
o.setAmbientColor = function(red, green, blue)
|
||||
o.ambient = {red, green, blue}
|
||||
end
|
||||
-- set ambient red
|
||||
o.setAmbientRed = function(red)
|
||||
o.ambient[1] = red
|
||||
end
|
||||
-- set ambient green
|
||||
o.setAmbientGreen = function(green)
|
||||
o.ambient[2] = green
|
||||
end
|
||||
-- set ambient blue
|
||||
o.setAmbientBlue = function(blue)
|
||||
o.ambient[3] = blue
|
||||
end
|
||||
-- set blur
|
||||
o.setBlur = function(blur)
|
||||
o.blur = blur
|
||||
o.changed = true
|
||||
end
|
||||
-- new rectangle
|
||||
o.newRectangle = function(x, y, w, h)
|
||||
return love.light.newRectangle(o, x, y, w, h)
|
||||
end
|
||||
-- new circle
|
||||
o.newCircle = function(x, y, r)
|
||||
return love.light.newCircle(o, x, y, r)
|
||||
end
|
||||
-- new polygon
|
||||
o.newPolygon = function(...)
|
||||
return love.light.newPolygon(o, ...)
|
||||
end
|
||||
-- set polygon data
|
||||
o.setPoints = function(n, ...)
|
||||
o.poly[n].data = {...}
|
||||
end
|
||||
-- get circle count
|
||||
o.getCircleCount = function()
|
||||
return #o.circle
|
||||
end
|
||||
-- get polygon count
|
||||
o.getPolygonCount = function()
|
||||
return #o.poly
|
||||
end
|
||||
-- get polygon
|
||||
o.getPoints = function(n)
|
||||
return unpack(o.poly[n].data)
|
||||
end
|
||||
-- get light count
|
||||
o.getLightCount = function()
|
||||
return #o.lights
|
||||
end
|
||||
-- get light x position
|
||||
o.getLightX = function(n)
|
||||
return o.lights[n].x
|
||||
end
|
||||
-- get light y position
|
||||
o.getLightY = function(n)
|
||||
return o.lights[n].y
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
-- light object
|
||||
function love.light.newLight(p, x, y, red, green, blue, range)
|
||||
local o = {}
|
||||
o.shadow = love.graphics.newCanvas()
|
||||
o.shine = love.graphics.newCanvas()
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.red = red
|
||||
o.green = green
|
||||
o.blue = blue
|
||||
o.range = range
|
||||
o.smooth = 1.0
|
||||
o.glowSize = 0.1
|
||||
o.glowStrength = 0.0
|
||||
o.changed = true
|
||||
-- set position
|
||||
o.setPosition = function(x, y)
|
||||
if x ~= o.x or y ~= o.y then
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.changed = true
|
||||
end
|
||||
end
|
||||
-- set color
|
||||
o.setColor = function(red, green, blue)
|
||||
o.red = red
|
||||
o.green = green
|
||||
o.blue = blue
|
||||
--p.changed = true
|
||||
end
|
||||
-- set range
|
||||
o.setRange = function(range)
|
||||
if range ~= o.range then
|
||||
o.range = range
|
||||
o.changed = true
|
||||
end
|
||||
end
|
||||
-- set glow size
|
||||
o.setSmooth = function(smooth)
|
||||
o.smooth = smooth
|
||||
o.changed = true
|
||||
end
|
||||
-- set glow size
|
||||
o.setGlowSize = function(size)
|
||||
o.glowSize = size
|
||||
o.changed = true
|
||||
end
|
||||
-- set glow strength
|
||||
o.setGlowStrength = function(strength)
|
||||
o.glowStrength = strength
|
||||
o.changed = true
|
||||
end
|
||||
-- get type
|
||||
o.getType = function()
|
||||
return "light"
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
-- rectangle object
|
||||
function love.light.newRectangle(p, x, y, w, h)
|
||||
local o = {}
|
||||
p.poly[#p.poly + 1] = o
|
||||
o.id = #p.poly
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.w = w
|
||||
o.h = h
|
||||
o.ox = w / 2
|
||||
o.oy = h / 2
|
||||
o.shine = true
|
||||
p.changed = true
|
||||
o.data = {
|
||||
o.x - o.ox,
|
||||
o.y - o.oy,
|
||||
o.x - o.ox + o.w,
|
||||
o.y - o.oy,
|
||||
o.x - o.ox + o.w,
|
||||
o.y - o.oy + o.h,
|
||||
o.x - o.ox,
|
||||
o.y - o.oy + o.h
|
||||
}
|
||||
-- refresh
|
||||
o.refresh = function()
|
||||
o.data[1] = o.x - o.ox
|
||||
o.data[2] = o.y - o.oy
|
||||
o.data[3] = o.x - o.ox + o.w
|
||||
o.data[4] = o.y - o.oy
|
||||
o.data[5] = o.x - o.ox + o.w
|
||||
o.data[6] = o.y - o.oy + o.h
|
||||
o.data[7] = o.x - o.ox
|
||||
o.data[8] = o.y - o.oy + o.h
|
||||
end
|
||||
-- set position
|
||||
o.setPosition = function(x, y)
|
||||
if x ~= o.x or y ~= o.y then
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.refresh()
|
||||
p.changed = true
|
||||
end
|
||||
end
|
||||
-- set dimension
|
||||
o.setDimension = function(w, h)
|
||||
o.w = w
|
||||
o.h = h
|
||||
o.refresh()
|
||||
p.changed = true
|
||||
end
|
||||
-- set shadow on/off
|
||||
o.setShadow = function(b)
|
||||
o.castsNoShadow = not b
|
||||
p.changed = true
|
||||
end
|
||||
-- set shine on/off
|
||||
o.setShine = function(b)
|
||||
o.shine = b
|
||||
p.changed = true
|
||||
end
|
||||
-- get type
|
||||
o.getType = function()
|
||||
return "rectangle"
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
-- circle object
|
||||
function love.light.newCircle(p, x, y, radius)
|
||||
local o = {}
|
||||
p.circle[#p.circle + 1] = o
|
||||
o.id = #p.circle
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.radius = radius
|
||||
o.shine = true
|
||||
p.changed = true
|
||||
-- set position
|
||||
o.setPosition = function(x, y)
|
||||
if x ~= o.x or y ~= o.y then
|
||||
o.x = x
|
||||
o.y = y
|
||||
p.changed = true
|
||||
end
|
||||
end
|
||||
-- set radius
|
||||
o.setRadius = function(radius)
|
||||
if radius ~= o.radius then
|
||||
o.radius = radius
|
||||
p.changed = true
|
||||
end
|
||||
end
|
||||
-- get x
|
||||
o.getX = function()
|
||||
return o.x
|
||||
end
|
||||
-- get y
|
||||
o.getY = function()
|
||||
return o.y
|
||||
end
|
||||
-- get radius
|
||||
o.getRadius = function()
|
||||
return o.radius
|
||||
end
|
||||
-- get type
|
||||
o.getType = function()
|
||||
return "circle"
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
-- poly object
|
||||
function love.light.newPolygon(p, ...)
|
||||
local o = {}
|
||||
p.poly[#p.poly + 1] = o
|
||||
o.id = #p.poly
|
||||
o.shine = true
|
||||
p.changed = true
|
||||
if ... then
|
||||
o.data = {...}
|
||||
else
|
||||
o.data = {0,0,0,0,0,0}
|
||||
end
|
||||
-- set polygon data
|
||||
o.setPoints = function(...)
|
||||
o.data = {...}
|
||||
p.changed = true
|
||||
end
|
||||
-- get polygon data
|
||||
o.getPoints = function()
|
||||
return unpack(o.data)
|
||||
end
|
||||
-- get type
|
||||
o.getType = function()
|
||||
return "polygon"
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
-- vector functions
|
||||
function normalize(v)
|
||||
local len = math.sqrt(math.pow(v[1], 2) + math.pow(v[2], 2))
|
||||
local normalizedv = {v[1] / len, v[2] / len}
|
||||
return normalizedv
|
||||
end
|
||||
|
||||
function dot(v1, v2)
|
||||
return v1[1] * v2[1] + v1[2] * v2[2]
|
||||
end
|
||||
|
||||
function lengthSqr(v)
|
||||
return v[1] * v[1] + v[2] * v[2]
|
||||
end
|
||||
|
||||
function length(v)
|
||||
return math.sqrt(lengthSqr(v))
|
||||
end
|
||||
|
||||
function calculateShadows(lightsource, geometry, circle)
|
||||
local shadowGeometry = {}
|
||||
local shadowLength = 10000
|
||||
|
||||
for i, v in pairs(geometry) do
|
||||
curPolygon = v.data
|
||||
if not v.castsNoShadow then
|
||||
local edgeFacingTo = {}
|
||||
for j=1,#curPolygon,2 do
|
||||
local indexOfNextVertex = (j+2) % #curPolygon
|
||||
local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[j+1], curPolygon[indexOfNextVertex] - curPolygon[j]}
|
||||
local lightToPoint = {curPolygon[j] - lightsource.x, curPolygon[j+1] - lightsource.y}
|
||||
|
||||
normal = normalize(normal)
|
||||
lightToPoint = normalize(lightToPoint)
|
||||
|
||||
local dotProduct = dot(normal, lightToPoint)
|
||||
if dotProduct > 0 then table.insert(edgeFacingTo, true)
|
||||
else table.insert(edgeFacingTo, false) end
|
||||
end
|
||||
|
||||
local curShadowGeometry = {}
|
||||
for j, curFacing in pairs(edgeFacingTo) do
|
||||
local nextIndex = (j+1) % #edgeFacingTo; if nextIndex == 0 then nextIndex = #edgeFacingTo end
|
||||
if curFacing and not edgeFacingTo[nextIndex] then
|
||||
curShadowGeometry[1] = curPolygon[nextIndex*2-1]
|
||||
curShadowGeometry[2] = curPolygon[nextIndex*2]
|
||||
|
||||
local lightVecFrontBack = normalize({curPolygon[nextIndex*2-1] - lightsource.x, curPolygon[nextIndex*2] - lightsource.y})
|
||||
curShadowGeometry[3] = curShadowGeometry[1] + lightVecFrontBack[1] * shadowLength
|
||||
curShadowGeometry[4] = curShadowGeometry[2] + lightVecFrontBack[2] * shadowLength
|
||||
|
||||
elseif not curFacing and edgeFacingTo[nextIndex] then
|
||||
curShadowGeometry[7] = curPolygon[nextIndex*2-1]
|
||||
curShadowGeometry[8] = curPolygon[nextIndex*2]
|
||||
|
||||
local lightVecBackFront = normalize({curPolygon[nextIndex*2-1] - lightsource.x, curPolygon[nextIndex*2] - lightsource.y})
|
||||
curShadowGeometry[5] = curShadowGeometry[7] + lightVecBackFront[1]*shadowLength
|
||||
curShadowGeometry[6] = curShadowGeometry[8] + lightVecBackFront[2]*shadowLength
|
||||
end
|
||||
end
|
||||
if curShadowGeometry[1]
|
||||
and curShadowGeometry[2]
|
||||
and curShadowGeometry[3]
|
||||
and curShadowGeometry[4]
|
||||
and curShadowGeometry[5]
|
||||
and curShadowGeometry[6]
|
||||
and curShadowGeometry[7]
|
||||
and curShadowGeometry[8]
|
||||
then
|
||||
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, v in pairs(circle) do
|
||||
local curShadowGeometry = {}
|
||||
local angle = math.atan2(lightsource.x - v.x, v.y - lightsource.y) + math.pi / 2
|
||||
local x2 = v.x + math.sin(angle) * v.radius
|
||||
local y2 = v.y - math.cos(angle) * v.radius
|
||||
local x3 = v.x - math.sin(angle) * v.radius
|
||||
local y3 = v.y + math.cos(angle) * v.radius
|
||||
|
||||
curShadowGeometry[1] = x2
|
||||
curShadowGeometry[2] = y2
|
||||
curShadowGeometry[3] = x3
|
||||
curShadowGeometry[4] = y3
|
||||
|
||||
curShadowGeometry[5] = x3 - (lightsource.x - x3) * shadowLength
|
||||
curShadowGeometry[6] = y3 - (lightsource.y - y3) * shadowLength
|
||||
curShadowGeometry[7] = x2 - (lightsource.x - x2) * shadowLength
|
||||
curShadowGeometry[8] = y2 - (lightsource.y - y2) * shadowLength
|
||||
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
|
||||
end
|
||||
|
||||
return shadowGeometry
|
||||
end
|
||||
|
||||
shadowStencil = function()
|
||||
local shadowGeometry = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_POLY, LOVE_LIGHT_CIRCLE)
|
||||
for i=1,#shadowGeometry do
|
||||
love.graphics.polygon("fill", unpack(shadowGeometry[i]))
|
||||
end
|
||||
for i=1, #LOVE_LIGHT_POLY do
|
||||
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
|
||||
end
|
||||
for i=1, #LOVE_LIGHT_CIRCLE do
|
||||
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].getX(), LOVE_LIGHT_CIRCLE[i].getY(), LOVE_LIGHT_CIRCLE[i].getRadius())
|
||||
end
|
||||
end
|
||||
|
||||
polyStencil = function()
|
||||
for i=1, #LOVE_LIGHT_POLY do
|
||||
if LOVE_LIGHT_POLY[i].shine then
|
||||
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
|
||||
end
|
||||
end
|
||||
for i=1, #LOVE_LIGHT_CIRCLE do
|
||||
if LOVE_LIGHT_CIRCLE[i].shine then
|
||||
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].getX(), LOVE_LIGHT_CIRCLE[i].getY(), LOVE_LIGHT_CIRCLE[i].getRadius())
|
||||
end
|
||||
end
|
||||
end
|
236
main.lua
Normal file
236
main.lua
Normal file
@ -0,0 +1,236 @@
|
||||
require "postshader"
|
||||
require "light"
|
||||
|
||||
function initScene()
|
||||
-- physic world
|
||||
physicWorld = love.physics.newWorld(0, 9.81 * 64, true)
|
||||
wall1 = {}
|
||||
wall1.body = love.physics.newBody(physicWorld, 400, 605, "static")
|
||||
wall1.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
||||
wall1.fixture = love.physics.newFixture(wall1.body, wall1.shape)
|
||||
|
||||
wall2 = {}
|
||||
wall2.body = love.physics.newBody(physicWorld, -5, 300, "static")
|
||||
wall2.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
||||
wall2.fixture = love.physics.newFixture(wall2.body, wall2.shape)
|
||||
|
||||
wall3 = {}
|
||||
wall3.body = love.physics.newBody(physicWorld, 805, 300, "static")
|
||||
wall3.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
||||
wall3.fixture = love.physics.newFixture(wall3.body, wall3.shape)
|
||||
|
||||
wall4 = {}
|
||||
wall4.body = love.physics.newBody(physicWorld, 400, -5, "static")
|
||||
wall4.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
||||
wall4.fixture = love.physics.newFixture(wall4.body, wall4.shape)
|
||||
|
||||
myPoly1 = lightWorld.newPolygon(wall1.body:getWorldPoints(wall1.shape:getPoints()))
|
||||
myPoly2 = lightWorld.newPolygon(wall2.body:getWorldPoints(wall2.shape:getPoints()))
|
||||
myPoly3 = lightWorld.newPolygon(wall3.body:getWorldPoints(wall3.shape:getPoints()))
|
||||
myPoly4 = lightWorld.newPolygon(wall4.body:getWorldPoints(wall4.shape:getPoints()))
|
||||
|
||||
phyCnt = 0
|
||||
phyLight = {}
|
||||
phyBody = {}
|
||||
phyShape = {}
|
||||
phyFixture = {}
|
||||
end
|
||||
|
||||
function love.load()
|
||||
love.graphics.setBackgroundColor(0, 0, 0)
|
||||
quadScreen = love.graphics.newQuad(0, 0, love.window.getWidth(), love.window.getHeight(), 32, 32)
|
||||
imgFloor = love.graphics.newImage("floor.png")
|
||||
imgFloor:setWrap("repeat", "repeat")
|
||||
|
||||
-- light world
|
||||
lightRange = 400
|
||||
lightSmooth = 1.0
|
||||
lightWorld = love.light.newWorld()
|
||||
lightWorld.setAmbientColor(15, 15, 15)
|
||||
mouseLight = lightWorld.newLight(0, 0, 255, 127, 63, lightRange)
|
||||
mouseLight.setGlowStrength(0.3)
|
||||
|
||||
-- init physic world
|
||||
initScene()
|
||||
|
||||
helpOn = true
|
||||
physicOn = true
|
||||
lightOn = true
|
||||
gravityOn = 1
|
||||
shadowBlurOn = true
|
||||
bloomOn = true
|
||||
textureOn = true
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
love.window.setTitle("FPS:" .. love.timer.getFPS())
|
||||
mouseLight.setPosition(love.mouse.getX(), love.mouse.getY())
|
||||
|
||||
for i = 1, phyCnt do
|
||||
if phyBody[i]:isAwake() then
|
||||
if phyShape[i]:getType() == "polygon" then
|
||||
phyLight[i].setPoints(phyBody[i]:getWorldPoints(phyShape[i]:getPoints()))
|
||||
else
|
||||
phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("w") then
|
||||
for i = 1, phyCnt do
|
||||
phyBody[i]:applyForce(0, -2000)
|
||||
end
|
||||
elseif love.keyboard.isDown("s") then
|
||||
for i = 1, phyCnt do
|
||||
phyBody[i]:applyForce(0, 2000)
|
||||
end
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("a") then
|
||||
for i = 1, phyCnt do
|
||||
phyBody[i]:applyForce(-2000, 0)
|
||||
end
|
||||
elseif love.keyboard.isDown("d") then
|
||||
for i = 1, phyCnt do
|
||||
phyBody[i]:applyForce(2000, 0)
|
||||
end
|
||||
end
|
||||
|
||||
if physicOn then
|
||||
physicWorld:update(dt)
|
||||
end
|
||||
|
||||
-- update lightmap
|
||||
if lightOn then
|
||||
lightWorld.update(dt)
|
||||
end
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
-- set shader buffer
|
||||
if bloomOn then
|
||||
love.postshader.setBuffer("render")
|
||||
end
|
||||
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
if textureOn then
|
||||
love.graphics.draw(imgFloor, quadScreen)
|
||||
else
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
end
|
||||
-- draw lightmap shadows
|
||||
if lightOn then
|
||||
lightWorld.drawShadow()
|
||||
end
|
||||
|
||||
for i = 1, phyCnt do
|
||||
love.graphics.setColor(math.sin(i) * 255, math.cos(i) * 255, math.tan(i) * 255)
|
||||
if phyLight[i].getType() == "polygon" then
|
||||
love.graphics.polygon("fill", phyLight[i].getPoints())
|
||||
else
|
||||
love.graphics.circle("fill", phyLight[i].getX(), phyLight[i].getY(), phyLight[i].getRadius())
|
||||
end
|
||||
end
|
||||
|
||||
-- draw lightmap shine
|
||||
if lightOn then
|
||||
lightWorld.drawShine()
|
||||
end
|
||||
|
||||
-- draw help
|
||||
if helpOn then
|
||||
love.graphics.setColor(0, 0, 0, 191)
|
||||
love.graphics.rectangle("fill", 8, 8, 210, 16 * 15)
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.print("WASD: Move objects", 16, 16)
|
||||
love.graphics.print("F1: Help on/off", 16, 32)
|
||||
love.graphics.print("F2: Physic on/off", 16, 48)
|
||||
love.graphics.print("F3: Light on/off", 16, 64)
|
||||
love.graphics.print("F4: Clear objects", 16, 80)
|
||||
love.graphics.print("F5: Clear lights", 16, 96)
|
||||
love.graphics.print("F6: Gravity on/off", 16, 112)
|
||||
love.graphics.print("F7: Shadowblur on/off", 16, 128)
|
||||
love.graphics.print("F8: Bloom on/off", 16, 144)
|
||||
love.graphics.print("F9: Texture on/off", 16, 160)
|
||||
love.graphics.print("M.left: Add cube", 16, 176)
|
||||
love.graphics.print("M.middle: Add light", 16, 192)
|
||||
love.graphics.print("M.right: Add circle", 16, 208)
|
||||
love.graphics.print("M.scroll: Change smooth", 16, 224)
|
||||
end
|
||||
|
||||
-- draw shader
|
||||
if bloomOn then
|
||||
love.postshader.draw("bloom")
|
||||
end
|
||||
end
|
||||
|
||||
function love.mousepressed(x, y, c)
|
||||
if c == "m" then
|
||||
-- add light
|
||||
local r = lightWorld.getLightCount() % 3
|
||||
local light
|
||||
|
||||
if r == 0 then
|
||||
light = lightWorld.newLight(x, y, 31, 127, 63, lightRange)
|
||||
elseif r == 1 then
|
||||
light = lightWorld.newLight(x, y, 127, 63, 31, lightRange)
|
||||
else
|
||||
light = lightWorld.newLight(x, y, 31, 63, 127, lightRange)
|
||||
end
|
||||
light.setSmooth(lightSmooth)
|
||||
light.setGlowStrength(0.3)
|
||||
elseif c == "l" then
|
||||
-- add rectangle
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld.newPolygon()
|
||||
phyBody[phyCnt] = love.physics.newBody(physicWorld, x, y, "dynamic")
|
||||
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, math.random(32, 64), math.random(32, 64))
|
||||
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
|
||||
phyFixture[phyCnt]:setRestitution(0.5)
|
||||
elseif c == "r" then
|
||||
-- add circle
|
||||
cRadius = math.random(8, 32)
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld.newCircle(x, y, cRadius)
|
||||
phyBody[phyCnt] = love.physics.newBody(physicWorld, x, y, "dynamic")
|
||||
phyShape[phyCnt] = love.physics.newCircleShape(0, 0, cRadius)
|
||||
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
|
||||
phyFixture[phyCnt]:setRestitution(0.5)
|
||||
elseif c == "wu" then
|
||||
lightSmooth = lightSmooth * 1.1
|
||||
mouseLight.setSmooth(lightSmooth)
|
||||
elseif c == "wd" then
|
||||
lightSmooth = lightSmooth / 1.1
|
||||
mouseLight.setSmooth(lightSmooth)
|
||||
end
|
||||
end
|
||||
|
||||
function love.keypressed(k, u)
|
||||
-- debug options
|
||||
if k == "f1" then
|
||||
helpOn = not helpOn
|
||||
elseif k == "f2" then
|
||||
physicOn = not physicOn
|
||||
elseif k == "f3" then
|
||||
lightOn = not lightOn
|
||||
elseif k == "f4" then
|
||||
physicWorld:destroy()
|
||||
lightWorld.clearObjects()
|
||||
initScene()
|
||||
elseif k == "f5" then
|
||||
lightWorld.clearLights()
|
||||
mouseLight = lightWorld.newLight(0, 0, 127, 63, 0, lightRange)
|
||||
mouseLight.setGlowStrength(0.3)
|
||||
elseif k == "f6" then
|
||||
gravityOn = 1 - gravityOn
|
||||
physicWorld:setGravity(0, gravityOn * 9.81 * 64)
|
||||
elseif k == "f7" then
|
||||
shadowBlurOn = not shadowBlurOn
|
||||
lightWorld.setBlur(shadowBlurOn)
|
||||
elseif k == "f8" then
|
||||
bloomOn = not bloomOn
|
||||
elseif k == "f9" then
|
||||
textureOn = not textureOn
|
||||
end
|
||||
end
|
63
postshader.lua
Normal file
63
postshader.lua
Normal file
@ -0,0 +1,63 @@
|
||||
LOVE_POSTSHADER_BUFFER_RENDER = love.graphics.newCanvas()
|
||||
LOVE_POSTSHADER_BUFFER_BACK = love.graphics.newCanvas()
|
||||
LOVE_POSTSHADER_LAST_BUFFER = nil
|
||||
|
||||
LOVE_POSTSHADER_BLURV = love.graphics.newShader("shader/blurv.glsl")
|
||||
LOVE_POSTSHADER_BLURH = love.graphics.newShader("shader/blurh.glsl")
|
||||
LOVE_POSTSHADER_CONTRAST = love.graphics.newShader("shader/contrast.glsl")
|
||||
|
||||
LOVE_POSTSHADER_BLURV:send("screen", {love.window.getWidth(), love.window.getHeight()})
|
||||
LOVE_POSTSHADER_BLURH:send("screen", {love.window.getWidth(), love.window.getHeight()})
|
||||
|
||||
love.postshader = {}
|
||||
|
||||
love.postshader.setBuffer = function(path)
|
||||
if path == "back" then
|
||||
love.graphics.setCanvas(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
else
|
||||
love.graphics.setCanvas(LOVE_POSTSHADER_BUFFER_RENDER)
|
||||
end
|
||||
end
|
||||
|
||||
love.postshader.draw = function(shader)
|
||||
LOVE_POSTSHADER_LAST_BUFFER = love.graphics.getCanvas()
|
||||
|
||||
if shader == "bloom" then
|
||||
-- Bloom Shader
|
||||
love.graphics.setCanvas(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
|
||||
love.graphics.setShader(LOVE_POSTSHADER_BLURV)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_RENDER)
|
||||
|
||||
love.graphics.setShader(LOVE_POSTSHADER_BLURH)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
|
||||
love.graphics.setShader(LOVE_POSTSHADER_CONTRAST)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
|
||||
love.graphics.setCanvas(LOVE_LIGHTMAP_LAST_BUFFER)
|
||||
love.graphics.setShader()
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_RENDER)
|
||||
love.graphics.setBlendMode("additive")
|
||||
love.graphics.setColor(255, 255, 255, 63)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
elseif shader == "blur" then
|
||||
-- Blur Shader
|
||||
love.graphics.setCanvas(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
|
||||
love.graphics.setShader(LOVE_POSTSHADER_BLURV)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_RENDER)
|
||||
|
||||
love.graphics.setShader(LOVE_POSTSHADER_BLURH)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
|
||||
love.graphics.setCanvas(LOVE_LIGHTMAP_LAST_BUFFER)
|
||||
love.graphics.setShader()
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.draw(LOVE_POSTSHADER_BUFFER_BACK)
|
||||
end
|
||||
end
|
14
shader/blurh.glsl
Normal file
14
shader/blurh.glsl
Normal file
@ -0,0 +1,14 @@
|
||||
extern vec2 screen = vec2(800.0, 600.0);
|
||||
|
||||
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
|
||||
vec2 pSize = vec2(1.0 / screen.x, 1.0 / screen.y);
|
||||
vec4 col = Texel(texture, texture_coords);
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * 2));
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * 2));
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y - pSize.y * 3));
|
||||
col = col + Texel(texture, vec2(texture_coords.x, texture_coords.y + pSize.y * 3));
|
||||
col = col / 7.0;
|
||||
return vec4(col.r, col.g, col.b, 1.0);
|
||||
}
|
14
shader/blurv.glsl
Normal file
14
shader/blurv.glsl
Normal file
@ -0,0 +1,14 @@
|
||||
extern vec2 screen = vec2(800.0, 600.0);
|
||||
|
||||
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
|
||||
vec2 pSize = vec2(1.0 / screen.x, 1.0 / screen.y);
|
||||
vec4 col = Texel(texture, texture_coords);
|
||||
col = col + Texel(texture, vec2(texture_coords.x - pSize.x, texture_coords.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x + pSize.x, texture_coords.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x - pSize.x * 2, texture_coords.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x + pSize.x * 2, texture_coords.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x - pSize.x * 3, texture_coords.y));
|
||||
col = col + Texel(texture, vec2(texture_coords.x + pSize.x * 3, texture_coords.y));
|
||||
col = col / 7.0;
|
||||
return vec4(col.r, col.g, col.b, 1.0);
|
||||
}
|
6
shader/contrast.glsl
Normal file
6
shader/contrast.glsl
Normal file
@ -0,0 +1,6 @@
|
||||
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
|
||||
{
|
||||
vec3 col = Texel(texture, texture_coords).rgb * 2.0;
|
||||
col *= col;
|
||||
return vec4(col, 1.0);
|
||||
}
|
23
shader/light.glsl
Normal file
23
shader/light.glsl
Normal file
@ -0,0 +1,23 @@
|
||||
extern vec3 lightPositionRange;
|
||||
extern vec3 lightColor;
|
||||
extern float smooth = 1.0;
|
||||
extern vec2 glow = vec2(0.95, 0.2);
|
||||
|
||||
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){
|
||||
vec4 pixel = Texel(texture, texture_coords);
|
||||
vec2 lightToPixel = pixel_coords - lightPositionRange.xy;
|
||||
float distance = length(lightToPixel);
|
||||
float att = 1 - distance / lightPositionRange.z;
|
||||
|
||||
if (distance <= lightPositionRange.z) {
|
||||
if (glow.x < 1.0 && glow.y > 0.0) {
|
||||
pixel.rgb = lightColor * pow(att, smooth) + pow(smoothstep(glow.x, 1.0, att), smooth) * glow.y;
|
||||
} else {
|
||||
pixel.rgb = lightColor * pow(att, smooth);
|
||||
}
|
||||
} else {
|
||||
pixel.rgb = vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
return pixel;
|
||||
}
|
Loading…
Reference in New Issue
Block a user