refactoring to be a bit more sane and so I can understand the codebase a bit better

This commit is contained in:
Tim Anema 2014-09-26 12:48:46 -04:00
parent b353eff979
commit d58fd39f7f
9 changed files with 1717 additions and 1710 deletions

View File

@ -1,6 +1,6 @@
-- Example: Complex Example
require "lib/postshader"
require "lib/light"
require "lib/light_world"
function initScene()
-- physic world
@ -94,8 +94,8 @@ function love.load()
lightWorld.setRefractionStrength(16.0)
lightWorld.setReflectionVisibility(0.75)
mouseLight = lightWorld.newLight(0, 0, 255, 191, 127, lightRange)
mouseLight.setGlowStrength(0.3)
mouseLight.setSmooth(lightSmooth)
mouseLight:setGlowStrength(0.3)
mouseLight:setSmooth(lightSmooth)
mouseLight.z = 63
lightDirection = 0.0
colorAberration = 0.0
@ -126,7 +126,7 @@ end
function love.update(dt)
love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")")
mouseLight.setPosition(love.mouse.getX(), love.mouse.getY(), 16.0 + (math.sin(lightDirection) + 1.0) * 64.0)
mouseLight:setPosition(love.mouse.getX(), love.mouse.getY(), 16.0 + (math.sin(lightDirection) + 1.0) * 64.0)
mx = love.mouse.getX()
my = love.mouse.getY()
lightDirection = lightDirection + dt
@ -194,22 +194,22 @@ function love.update(dt)
phyBody[i]:setX(phyBody[i]:getX() + (offsetX - offsetOldX))
phyBody[i]:setY(phyBody[i]:getY() + (offsetY - offsetOldY))
end
if phyLight[i].getType() == "polygon" then
phyLight[i].setPoints(phyBody[i]:getWorldPoints(phyShape[i]:getPoints()))
elseif phyLight[i].getType() == "circle" then
phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY())
elseif phyLight[i].getType() == "image" then
phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY())
elseif phyLight[i].getType() == "refraction" then
--phyLight[i].setPosition(phyBody[i]:getX(), phyBody[i]:getY())
if phyLight[i]:getType() == "polygon" then
phyLight[i]:setPoints(phyBody[i]:getWorldPoints(phyShape[i]:getPoints()))
elseif phyLight[i]:getType() == "circle" then
phyLight[i]:setPosition(phyBody[i]:getX(), phyBody[i]:getY())
elseif phyLight[i]:getType() == "image" then
phyLight[i]:setPosition(phyBody[i]:getX(), phyBody[i]:getY())
elseif phyLight[i]:getType() == "refraction" then
--phyLight[i]:setPosition(phyBody[i]:getX(), phyBody[i]:getY())
end
end
if phyLight[i].getType() == "refraction" then
if phyLight[i]:getType() == "refraction" then
--if math.mod(i, 2) == 0 then
phyLight[i].setNormalTileOffset(tileX, tileY)
phyLight[i]:setNormalTileOffset(tileX, tileY)
--end
if offsetChanged then
phyLight[i].setPosition(phyLight[i].getX() + (offsetX - offsetOldX), phyLight[i].getY() + (offsetY - offsetOldY))
phyLight[i]:setPosition(phyLight[i].getX() + (offsetX - offsetOldX), phyLight[i].getY() + (offsetY - offsetOldY))
end
end
end
@ -247,7 +247,7 @@ function love.draw()
end
for i = 1, phyCnt do
if phyLight[i].getType() == "refraction" then
if phyLight[i]:getType() == "refraction" then
if not normalOn then
--if math.mod(i, 2) == 0 then
love.graphics.setBlendMode("alpha")
@ -271,10 +271,10 @@ function love.draw()
for i = 1, phyCnt do
math.randomseed(i)
love.graphics.setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
if phyLight[i].getType() == "polygon" then
love.graphics.polygon("fill", phyLight[i].getPoints())
elseif phyLight[i].getType() == "circle" then
love.graphics.circle("fill", phyLight[i].getX(), phyLight[i].getY(), phyLight[i].getRadius())
if phyLight[i]:getType() == "polygon" then
love.graphics.polygon("fill", phyLight[i]:getPoints())
elseif phyLight[i]:getType() == "circle" then
love.graphics.circle("fill", phyLight[i]:getX(), phyLight[i]:getY(), phyLight[i]:getRadius())
end
end
@ -285,7 +285,7 @@ function love.draw()
love.graphics.setBlendMode("alpha")
for i = 1, phyCnt do
if phyLight[i].getType() == "image" then
if phyLight[i]:getType() == "image" then
if normalOn and phyLight[i].normal then
love.graphics.setColor(255, 255, 255)
love.graphics.draw(phyLight[i].normal, phyLight[i].x - phyLight[i].nx, phyLight[i].y - phyLight[i].ny)
@ -448,8 +448,8 @@ function love.mousepressed(x, y, c)
else
light = lightWorld.newLight(x, y, 31, 63, 127, lightRange)
end
light.setSmooth(lightSmooth)
light.setGlowStrength(0.3)
light:setSmooth(lightSmooth)
light:setGlowStrength(0.3)
elseif c == "l" then
-- add rectangle
math.randomseed(love.timer.getTime())
@ -472,12 +472,12 @@ function love.mousepressed(x, y, c)
elseif c == "wu" then
if lightSmooth < 4.0 then
lightSmooth = lightSmooth * 1.1
mouseLight.setSmooth(lightSmooth)
mouseLight:setSmooth(lightSmooth)
end
elseif c == "wd" then
if lightSmooth > 0.5 then
lightSmooth = lightSmooth / 1.1
mouseLight.setSmooth(lightSmooth)
mouseLight:setSmooth(lightSmooth)
end
end
end
@ -526,14 +526,14 @@ function love.keypressed(k, u)
elseif k == "f12" then
lightWorld.clearLights()
mouseLight = lightWorld.newLight(0, 0, 255, 191, 127, lightRange)
mouseLight.setGlowStrength(0.3)
mouseLight.setSmooth(lightSmooth)
mouseLight:setGlowStrength(0.3)
mouseLight:setSmooth(lightSmooth)
elseif k == "1" then
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(circle, mx, my)
phyLight[phyCnt].setNormalMap(circle_normal)
phyLight[phyCnt].setShadowType("circle", 16)
phyLight[phyCnt]:setNormalMap(circle_normal)
phyLight[phyCnt]:setShadowType("circle", 16)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -544,8 +544,8 @@ function love.keypressed(k, u)
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(cone, mx, my, 24, 12, 12, 16)
phyLight[phyCnt].setNormalMap(cone_normal)
phyLight[phyCnt].setShadowType("circle", 12, 0, -8)
phyLight[phyCnt]:setNormalMap(cone_normal)
phyLight[phyCnt]:setShadowType("circle", 12, 0, -8)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -554,7 +554,7 @@ function love.keypressed(k, u)
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(chest, mx, my, 32, 24, 16, 0)
phyLight[phyCnt].setNormalMap(chest_normal)
phyLight[phyCnt]:setNormalMap(chest_normal)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 24)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -565,24 +565,24 @@ function love.keypressed(k, u)
local r = lightWorld.getBodyCount() % #material
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(ape, mx, my, 160, 128, 80, 64)
phyLight[phyCnt].setNormalMap(ape_normal)
phyLight[phyCnt]:setNormalMap(ape_normal)
if r == 3 then
phyLight[phyCnt].setGlowMap(ape_glow)
phyLight[phyCnt]:setGlowMap(ape_glow)
end
phyLight[phyCnt].setMaterial(material[r + 1])
phyLight[phyCnt]:setMaterial(material[r + 1])
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 24)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5)
phyLight[phyCnt].setShadowType("image", 0, -16, 0.0)
phyLight[phyCnt]:setShadowType("image", 0, -16, 0.0)
elseif k == "4" then
-- add glow image
local r = lightWorld.getBodyCount() % 5
if r == 0 then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(machine, mx, my, 32, 24, 16, 0)
phyLight[phyCnt].setNormalMap(machine_normal)
phyLight[phyCnt].setGlowMap(machine_glow)
phyLight[phyCnt]:setNormalMap(machine_normal)
phyLight[phyCnt]:setGlowMap(machine_glow)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 24)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -590,8 +590,8 @@ function love.keypressed(k, u)
elseif r == 1 then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(machine2, mx, my, 24, 12, 12, -4)
phyLight[phyCnt].setNormalMap(machine2_normal)
phyLight[phyCnt].setGlowMap(machine2_glow)
phyLight[phyCnt]:setNormalMap(machine2_normal)
phyLight[phyCnt]:setGlowMap(machine2_glow)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -599,8 +599,8 @@ function love.keypressed(k, u)
elseif r == 2 then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(led, mx, my, 32, 6, 16, -8)
phyLight[phyCnt].setNormalMap(led_normal)
phyLight[phyCnt].setGlowMap(led_glow)
phyLight[phyCnt]:setNormalMap(led_normal)
phyLight[phyCnt]:setGlowMap(led_glow)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 6)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -608,8 +608,8 @@ function love.keypressed(k, u)
elseif r == 3 then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(led2, mx, my, 32, 6, 16, -8)
phyLight[phyCnt].setNormalMap(led_normal)
phyLight[phyCnt].setGlowMap(led_glow2)
phyLight[phyCnt]:setNormalMap(led_normal)
phyLight[phyCnt]:setGlowMap(led_glow2)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 6)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -617,8 +617,8 @@ function love.keypressed(k, u)
elseif r == 4 then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(led3, mx, my, 32, 6, 16, -8)
phyLight[phyCnt].setNormalMap(led_normal)
phyLight[phyCnt].setGlowMap(led_glow3)
phyLight[phyCnt]:setNormalMap(led_normal)
phyLight[phyCnt]:setGlowMap(led_glow3)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 32, 6)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -628,8 +628,8 @@ function love.keypressed(k, u)
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(cone_large, mx, my, 24, 128, 12, 64)
phyLight[phyCnt].setNormalMap(cone_large_normal)
phyLight[phyCnt].setShadowType("image", 0, -6, 0.0)
phyLight[phyCnt]:setNormalMap(cone_large_normal)
phyLight[phyCnt]:setShadowType("image", 0, -6, 0.0)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 24, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -638,8 +638,8 @@ function love.keypressed(k, u)
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(blopp, mx, my, 42, 16, 21, 0)
phyLight[phyCnt].generateNormalMapGradient("gradient", "gradient")
phyLight[phyCnt].setAlpha(0.5)
phyLight[phyCnt]:generateNormalMapGradient("gradient", "gradient")
phyLight[phyCnt]:setAlpha(0.5)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 42, 29)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -648,9 +648,9 @@ function love.keypressed(k, u)
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(tile, mx, my)
phyLight[phyCnt].setHeightMap(tile_normal, 2.0)
phyLight[phyCnt].setGlowMap(tile_glow)
phyLight[phyCnt].setShadow(false)
phyLight[phyCnt]:setHeightMap(tile_normal, 2.0)
phyLight[phyCnt]:setGlowMap(tile_glow)
phyLight[phyCnt]:setShadow(false)
phyLight[phyCnt].reflective = false
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 64, 64)
@ -660,29 +660,29 @@ function love.keypressed(k, u)
-- add rectangle
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newPolygon()
phyLight[phyCnt].setAlpha(0.5)
phyLight[phyCnt].setGlowStrength(1.0)
phyLight[phyCnt]:setAlpha(0.5)
phyLight[phyCnt]:setGlowStrength(1.0)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
math.randomseed(love.timer.getTime())
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)
math.randomseed(phyCnt)
phyLight[phyCnt].setGlowColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
phyLight[phyCnt]:setGlowColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
math.randomseed(phyCnt)
phyLight[phyCnt].setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
phyLight[phyCnt]:setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
elseif k == "9" then
-- add circle
math.randomseed(love.timer.getTime())
cRadius = math.random(8, 32)
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newCircle(mx, my, cRadius)
phyLight[phyCnt].setAlpha(0.5)
phyLight[phyCnt].setGlowStrength(1.0)
phyLight[phyCnt]:setAlpha(0.5)
phyLight[phyCnt]:setGlowStrength(1.0)
math.randomseed(phyCnt)
phyLight[phyCnt].setGlowColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
phyLight[phyCnt]:setGlowColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
math.randomseed(phyCnt)
phyLight[phyCnt].setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
phyLight[phyCnt]:setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newCircleShape(0, 0, cRadius)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -690,7 +690,7 @@ function love.keypressed(k, u)
elseif k == "0" then
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newRefraction(refraction_normal, mx, my)
phyLight[phyCnt].setReflection(true)
phyLight[phyCnt]:setReflection(true)
elseif k == "l" then
-- add light
local r = lightWorld.getLightCount() % 3

View File

@ -1,6 +1,6 @@
-- Example: Short Example
require "lib/postshader"
require "lib/light"
require "lib/light_world"
function love.load()
-- load images
@ -16,23 +16,23 @@ function love.load()
-- create light
lightMouse = lightWorld.newLight(0, 0, 255, 127, 63, 300)
lightMouse.setGlowStrength(0.3)
--lightMouse.setSmooth(0.01)
lightMouse:setGlowStrength(0.3)
--lightMouse:setSmooth(0.01)
-- create shadow bodys
circleTest = lightWorld.newCircle(256, 256, 16)
rectangleTest = lightWorld.newRectangle(512, 512, 64, 64)
imageTest = lightWorld.newImage(image, 64, 64, 24, 6)
imageTest.setNormalMap(image_normal)
imageTest.setGlowMap(glow)
imageTest.setOffset(12, -10)
imageTest:setNormalMap(image_normal)
imageTest:setGlowMap(glow)
imageTest:setOffset(12, -10)
-- create body object
objectTest = lightWorld.newBody("refraction", normal, 64, 64, 128, 128)
--objectTest.setShine(false)
--objectTest.setShadowType("rectangle")
--objectTest.setShadowDimension(64, 64)
objectTest.setReflection(true)
--objectTest:setShine(false)
--objectTest:setShadowType("rectangle")
--objectTest:setShadowDimension(64, 64)
objectTest:setReflection(true)
-- set background
quadScreen = love.graphics.newQuad(0, 0, love.window.getWidth(), love.window.getHeight(), 32, 24)
@ -42,7 +42,7 @@ end
function love.update(dt)
love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")")
lightMouse.setPosition(love.mouse.getX(), love.mouse.getY())
lightMouse:setPosition(love.mouse.getX(), love.mouse.getY())
end
function love.draw()
@ -61,8 +61,8 @@ function love.draw()
-- draw scene objects
love.graphics.setColor(63, 255, 127)
love.graphics.circle("fill", circleTest.getX(), circleTest.getY(), circleTest.getRadius())
love.graphics.polygon("fill", rectangleTest.getPoints())
love.graphics.circle("fill", circleTest:getX(), circleTest:getY(), circleTest:getRadius())
love.graphics.polygon("fill", rectangleTest:getPoints())
love.graphics.setColor(255, 255, 255)
love.graphics.draw(image, 64 - image:getWidth() * 0.5, 64 - image:getHeight() * 0.5)

529
lib/body.lua Normal file
View File

@ -0,0 +1,529 @@
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
local class = require(_PACKAGE.."/class")
local body = class(function(o, world, id, type, ...)
local args = {...}
o.id = id
o.type = type
o.normal = nil
o.material = nil
o.glow = nil
o.world = world
if o.type == "circle" then
o.x = args[1] or 0
o.y = args[2] or 0
o.radius = args[3] or 16
o.ox = args[4] or 0
o.oy = args[5] or 0
o.shadowType = "circle"
o.reflection = false
o.reflective = false
o.refraction = false
o.refractive = false
world.isShadows = true
elseif o.type == "rectangle" then
o.x = args[1] or 0
o.y = args[2] or 0
o.width = args[3] or 64
o.height = args[4] or 64
o.ox = o.width * 0.5
o.oy = o.height * 0.5
o.shadowType = "rectangle"
o.data = {
o.x - o.ox,
o.y - o.oy,
o.x - o.ox + o.width,
o.y - o.oy,
o.x - o.ox + o.width,
o.y - o.oy + o.height,
o.x - o.ox,
o.y - o.oy + o.height
}
o.reflection = false
o.reflective = false
o.refraction = false
o.refractive = false
world.isShadows = true
elseif o.type == "polygon" then
o.shadowType = "polygon"
o.data = args or {0, 0, 0, 0, 0, 0}
o.reflection = false
o.reflective = false
o.refraction = false
o.refractive = false
world.isShadows = true
elseif o.type == "image" then
o.img = args[1]
o.x = args[2] or 0
o.y = args[3] or 0
if o.img then
o.imgWidth = o.img:getWidth()
o.imgHeight = o.img:getHeight()
o.width = args[4] or o.imgWidth
o.height = args[5] or o.imgHeight
o.ix = o.imgWidth * 0.5
o.iy = o.imgHeight * 0.5
o.vert = {
{ 0.0, 0.0, 0.0, 0.0 },
{ o.width, 0.0, 1.0, 0.0 },
{ o.width, o.height, 1.0, 1.0 },
{ 0.0, o.height, 0.0, 1.0 },
}
o.msh = love.graphics.newMesh(o.vert, o.img, "fan")
else
o.width = args[4] or 64
o.height = args[5] or 64
end
o.ox = args[6] or o.width * 0.5
o.oy = args[7] or o.height * 0.5
o.shadowType = "rectangle"
o.data = {
o.x - o.ox,
o.y - o.oy,
o.x - o.ox + o.width,
o.y - o.oy,
o.x - o.ox + o.width,
o.y - o.oy + o.height,
o.x - o.ox,
o.y - o.oy + o.height
}
o.reflection = false
o.reflective = true
o.refraction = false
o.refractive = false
world.isShadows = true
elseif o.type == "refraction" then
o.normal = args[1]
o.x = args[2] or 0
o.y = args[3] or 0
if o.normal then
o.normalWidth = o.normal:getWidth()
o.normalHeight = o.normal:getHeight()
o.width = args[4] or o.normalWidth
o.height = args[5] or o.normalHeight
o.nx = o.normalWidth * 0.5
o.ny = o.normalHeight * 0.5
o.normal:setWrap("repeat", "repeat")
o.normalVert = {
{0.0, 0.0, 0.0, 0.0},
{o.width, 0.0, 1.0, 0.0},
{o.width, o.height, 1.0, 1.0},
{0.0, o.height, 0.0, 1.0}
}
o.normalMesh = love.graphics.newMesh(o.normalVert, o.normal, "fan")
else
o.width = args[4] or 64
o.height = args[5] or 64
end
o.ox = o.width * 0.5
o.oy = o.height * 0.5
o.reflection = false
o.reflective = false
o.refraction = true
o.refractive = false
world.isRefraction = true
elseif o.type == "reflection" then
o.normal = args[1]
o.x = args[2] or 0
o.y = args[3] or 0
if o.normal then
o.normalWidth = o.normal:getWidth()
o.normalHeight = o.normal:getHeight()
o.width = args[4] or o.normalWidth
o.height = args[5] or o.normalHeight
o.nx = o.normalWidth * 0.5
o.ny = o.normalHeight * 0.5
o.normal:setWrap("repeat", "repeat")
o.normalVert = {
{0.0, 0.0, 0.0, 0.0},
{o.width, 0.0, 1.0, 0.0},
{o.width, o.height, 1.0, 1.0},
{0.0, o.height, 0.0, 1.0}
}
o.normalMesh = love.graphics.newMesh(o.normalVert, o.normal, "fan")
else
o.width = args[4] or 64
o.height = args[5] or 64
end
o.ox = o.width * 0.5
o.oy = o.height * 0.5
o.reflection = true
o.reflective = false
o.refraction = false
o.refractive = false
world.isReflection = true
end
o.shine = true
o.red = 0
o.green = 0
o.blue = 0
o.alpha = 1.0
o.glowRed = 255
o.glowGreen = 255
o.glowBlue = 255
o.glowStrength = 0.0
o.tileX = 0
o.tileY = 0
end)
-- refresh
function body:refresh()
if self.data then
self.data[1] = self.x - self.ox
self.data[2] = self.y - self.oy
self.data[3] = self.x - self.ox + self.width
self.data[4] = self.y - self.oy
self.data[5] = self.x - self.ox + self.width
self.data[6] = self.y - self.oy + self.height
self.data[7] = self.x - self.ox
self.data[8] = self.y - self.oy + self.height
end
end
-- set position
function body:setPosition(x, y)
if x ~= self.x or y ~= self.y then
self.x = x
self.y = y
self:refresh()
self.world.changed = true
end
end
-- set x position
function body:setX(x)
if x ~= self.x then
self.x = x
self:refresh()
self.world.changed = true
end
end
-- set y position
function body:setY(y)
if y ~= self.y then
self.y = y
self:refresh()
self.world.changed = true
end
end
-- get x position
function body:getX()
return self.x
end
-- get y position
function body:getY(y)
return self.y
end
-- get width
function body:getWidth()
return self.width
end
-- get height
function body:getHeight()
return self.height
end
-- get image width
function body:getImageWidth()
return self.imgWidth
end
-- get image height
function body:getImageHeight()
return self.imgHeight
end
-- set dimension
function body:setDimension(width, height)
self.width = width
self.height = height
self:refresh()
self.world.changed = true
end
-- set offset
function body:setOffset(ox, oy)
if ox ~= self.ox or oy ~= self.oy then
self.ox = ox
self.oy = oy
if self.shadowType == "rectangle" then
self:refresh()
end
self.world.changed = true
end
end
-- set offset
function body:setImageOffset(ix, iy)
if ix ~= self.ix or iy ~= self.iy then
self.ix = ix
self.iy = iy
self:refresh()
self.world.changed = true
end
end
-- set offset
function body:setNormalOffset(nx, ny)
if nx ~= self.nx or ny ~= self.ny then
self.nx = nx
self.ny = ny
self:refresh()
self.world.changed = true
end
end
-- set glow color
function body:setGlowColor(red, green, blue)
self.glowRed = red
self.glowGreen = green
self.glowBlue = blue
self.world.changed = true
end
-- set glow alpha
function body:setGlowStrength(strength)
self.glowStrength = strength
self.world.changed = true
end
-- get radius
function body:getRadius()
return self.radius
end
-- set radius
function body:setRadius(radius)
if radius ~= self.radius then
self.radius = radius
self.world.changed = true
end
end
-- set polygon data
function body:setPoints(...)
self.data = {...}
self.world.changed = true
end
-- get polygon data
function body:getPoints()
return unpack(self.data)
end
-- set shadow on/off
function body:setShadowType(type)
self.shadowType = type
self.world.changed = true
end
-- set shadow on/off
function body:setShadow(b)
self.castsNoShadow = not b
self.world.changed = true
end
-- set shine on/off
function body:setShine(b)
self.shine = b
self.world.changed = true
end
-- set glass color
function body:setColor(red, green, blue)
self.red = red
self.green = green
self.blue = blue
self.world.changed = true
end
-- set glass alpha
function body:setAlpha(alpha)
self.alpha = alpha
self.world.changed = true
end
-- set reflection on/off
function body:setReflection(reflection)
self.reflection = reflection
end
-- set refraction on/off
function body:setRefraction(refraction)
self.refraction = refraction
end
-- set reflective on other objects on/off
function body:setReflective(reflective)
self.reflective = reflective
end
-- set refractive on other objects on/off
function body:setRefractive(refractive)
self.refractive = refractive
end
-- set image
function body:setImage(img)
if img then
self.img = img
self.imgWidth = self.img:getWidth()
self.imgHeight = self.img:getHeight()
self.ix = self.imgWidth * 0.5
self.iy = self.imgHeight * 0.5
end
end
-- set normal
function body:setNormalMap(normal, width, height, nx, ny)
if normal then
self.normal = normal
self.normal:setWrap("repeat", "repeat")
self.normalWidth = width or self.normal:getWidth()
self.normalHeight = height or self.normal:getHeight()
self.nx = nx or self.normalWidth * 0.5
self.ny = ny or self.normalHeight * 0.5
self.normalVert = {
{0.0, 0.0, 0.0, 0.0},
{self.normalWidth, 0.0, self.normalWidth / self.normal:getWidth(), 0.0},
{self.normalWidth, self.normalHeight, self.normalWidth / self.normal:getWidth(), self.normalHeight / self.normal:getHeight()},
{0.0, self.normalHeight, 0.0, self.normalHeight / self.normal:getHeight()}
}
self.normalMesh = love.graphics.newMesh(self.normalVert, self.normal, "fan")
self.world.isPixelShadows = true
else
self.normalMesh = nil
end
end
-- set height map
function body:setHeightMap(heightMap, strength)
self:setNormalMap(HeightMapToNormalMap(heightMap, strength))
end
-- generate flat normal map
function body:generateNormalMapFlat(mode)
local imgData = self.img:getData()
local imgNormalData = love.image.newImageData(self.imgWidth, self.imgHeight)
local color
if mode == "top" then
color = {127, 127, 255}
elseif mode == "front" then
color = {127, 0, 127}
elseif mode == "back" then
color = {127, 255, 127}
elseif mode == "left" then
color = {31, 0, 223}
elseif mode == "right" then
color = {223, 0, 127}
end
for i = 0, self.imgHeight - 1 do
for k = 0, self.imgWidth - 1 do
local r, g, b, a = imgData:getPixel(k, i)
if a > 0 then
imgNormalData:setPixel(k, i, color[1], color[2], color[3], 255)
end
end
end
self:setNormalMap(love.graphics.newImage(imgNormalData))
end
-- generate faded normal map
function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
local imgData = self.img:getData()
local imgNormalData = love.image.newImageData(self.imgWidth, self.imgHeight)
local dx = 255.0 / self.imgWidth
local dy = 255.0 / self.imgHeight
local nx
local ny
local nz
for i = 0, self.imgWidth - 1 do
for k = 0, self.imgHeight - 1 do
local r, g, b, a = imgData:getPixel(i, k)
if a > 0 then
if horizontalGradient == "gradient" then
nx = i * dx
elseif horizontalGradient == "inverse" then
nx = 255 - i * dx
else
nx = 127
end
if verticalGradient == "gradient" then
ny = 127 - k * dy * 0.5
nz = 255 - k * dy * 0.5
elseif verticalGradient == "inverse" then
ny = 127 + k * dy * 0.5
nz = 127 - k * dy * 0.25
else
ny = 255
nz = 127
end
imgNormalData:setPixel(i, k, nx, ny, nz, 255)
end
end
end
self:setNormalMap(love.graphics.newImage(imgNormalData))
end
-- generate normal map
function body:generateNormalMap(strength)
self:setNormalMap(HeightMapToNormalMap(self.img, strength))
end
-- set material
function body:setMaterial(material)
if material then
self.material = material
end
end
-- set normal
function body:setGlowMap(glow)
self.glow = glow
self.glowStrength = 1.0
self.world.isGlow = true
end
-- set tile offset
function body:setNormalTileOffset(tx, ty)
self.tileX = tx / self.normalWidth
self.tileY = ty / self.normalHeight
self.normalVert = {
{0.0, 0.0, self.tileX, self.tileY},
{self.normalWidth, 0.0, self.tileX + 1.0, self.tileY},
{self.normalWidth, self.normalHeight, self.tileX + 1.0, self.tileY + 1.0},
{0.0, self.normalHeight, self.tileX, self.tileY + 1.0}
}
self.world.changed = true
end
-- get type
function body:getType()
return self.type
end
-- get type
function body:setShadowType(type, ...)
self.shadowType = type
local args = {...}
if self.shadowType == "circle" then
self.radius = args[1] or 16
self.ox = args[2] or 0
self.oy = args[3] or 0
elseif self.shadowType == "rectangle" then
self.width = args[1] or 64
self.height = args[2] or 64
self.ox = args[3] or self.width * 0.5
self.oy = args[4] or self.height * 0.5
self.data = {
self.x - self.ox,
self.y - self.oy,
self.x - self.ox + self.width,
self.y - self.oy,
self.x - self.ox + self.width,
self.y - self.oy + self.height,
self.x - self.ox,
self.y - self.oy + self.height
}
elseif self.shadowType == "polygon" then
self.data = args or {0, 0, 0, 0, 0, 0}
elseif self.shadowType == "image" then
if self.img then
self.width = self.imgWidth
self.height = self.imgHeight
self.shadowVert = {
{0.0, 0.0, 0.0, 0.0},
{self.width, 0.0, 1.0, 0.0},
{self.width, self.height, 1.0, 1.0},
{0.0, self.height, 0.0, 1.0}
}
if not self.shadowMesh then
self.shadowMesh = love.graphics.newMesh(self.shadowVert, self.img, "fan")
self.shadowMesh:setVertexColors(true)
end
else
self.width = 64
self.height = 64
end
self.shadowX = args[1] or 0
self.shadowY = args[2] or 0
self.fadeStrength = args[3] or 0.0
end
end
return body

47
lib/class.lua Normal file
View File

@ -0,0 +1,47 @@
-- class.lua
-- Compatible with Lua 5.1 (not 5.0).
local class = function(base, init)
local c = {} -- a new class instance
if not init and type(base) == 'function' then
init = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a constructor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl, ...)
local obj = {}
setmetatable(obj,c)
if init then
init(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj, ...)
end
end
return obj
end
c.init = init
c.is_a = function(self, klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c, mt)
return c
end
return class

File diff suppressed because it is too large Load Diff

888
lib/light_world.lua Normal file
View File

@ -0,0 +1,888 @@
--[[
The MIT License (MIT)
Copyright (c) 2014 Marcus Ihde
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
local class = require(_PACKAGE..'/class')
local stencils = require(_PACKAGE..'/stencils')
local vector = require(_PACKAGE..'/vector')
local Light = require(_PACKAGE..'/light')
local Body = require(_PACKAGE..'/body')
LOVE_LIGHT_CURRENT = nil
LOVE_LIGHT_CIRCLE = nil
LOVE_LIGHT_POLY = nil
LOVE_LIGHT_IMAGE = nil
LOVE_LIGHT_BODY = nil
LOVE_LIGHT_LAST_BUFFER = nil
LOVE_LIGHT_SHADOW_GEOMETRY = nil
LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl")
LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl")
LOVE_LIGHT_BLURV:send("screen", {love.window.getWidth(), love.window.getHeight()})
LOVE_LIGHT_BLURH:send("screen", {love.window.getWidth(), love.window.getHeight()})
LOVE_LIGHT_TRANSLATE_X = 0
LOVE_LIGHT_TRANSLATE_Y = 0
LOVE_LIGHT_TRANSLATE_X_OLD = 0
LOVE_LIGHT_TRANSLATE_Y_OLD = 0
LOVE_LIGHT_DIRECTION = 0
love.light = {}
-- light world
function love.light.newWorld()
local o = {}
o.lights = {}
o.ambient = {0, 0, 0}
o.body = {}
o.refraction = {}
o.shadow = love.graphics.newCanvas()
o.shadow2 = love.graphics.newCanvas()
o.shine = love.graphics.newCanvas()
o.shine2 = love.graphics.newCanvas()
o.normalMap = love.graphics.newCanvas()
o.glowMap = love.graphics.newCanvas()
o.glowMap2 = love.graphics.newCanvas()
o.refractionMap = love.graphics.newCanvas()
o.refractionMap2 = love.graphics.newCanvas()
o.reflectionMap = love.graphics.newCanvas()
o.reflectionMap2 = love.graphics.newCanvas()
o.normalInvert = false
o.glowBlur = 1.0
o.glowTimer = 0.0
o.glowDown = false
o.refractionStrength = 8.0
o.pixelShadow = love.graphics.newCanvas()
o.pixelShadow2 = love.graphics.newCanvas()
o.shader = love.graphics.newShader("shader/poly_shadow.glsl")
o.glowShader = love.graphics.newShader("shader/glow.glsl")
o.normalShader = love.graphics.newShader("shader/normal.glsl")
o.normalInvertShader = love.graphics.newShader("shader/normal_invert.glsl")
o.materialShader = love.graphics.newShader("shader/material.glsl")
o.refractionShader = love.graphics.newShader("shader/refraction.glsl")
o.refractionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
o.reflectionShader = love.graphics.newShader("shader/reflection.glsl")
o.reflectionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
o.reflectionStrength = 16.0
o.reflectionVisibility = 1.0
o.changed = true
o.blur = 2.0
o.optionShadows = true
o.optionPixelShadows = true
o.optionGlow = true
o.optionRefraction = true
o.optionReflection = true
o.isShadows = false
o.isLight = false
o.isPixelShadows = false
o.isGlow = false
o.isRefraction = false
o.isReflection = false
-- update
o.update = function()
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
if LOVE_LIGHT_TRANSLATE_X ~= LOVE_LIGHT_TRANSLATE_X_OLD or LOVE_LIGHT_TRANSLATE_Y ~= LOVE_LIGHT_TRANSLATE_Y_OLD then
LOVE_LIGHT_TRANSLATE_X_OLD = LOVE_LIGHT_TRANSLATE_X
LOVE_LIGHT_TRANSLATE_Y_OLD = LOVE_LIGHT_TRANSLATE_Y
o.changed = true
end
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha")
if o.optionShadows and (o.isShadows or o.isLight) then
love.graphics.setShader(o.shader)
local lightsOnScreen = 0
LOVE_LIGHT_BODY = o.body
for i = 1, #o.lights do
if o.lights[i].changed or o.changed then
if o.lights[i].x + o.lights[i].range > LOVE_LIGHT_TRANSLATE_X and o.lights[i].x - o.lights[i].range < love.graphics.getWidth() + LOVE_LIGHT_TRANSLATE_X
and o.lights[i].y + o.lights[i].range > LOVE_LIGHT_TRANSLATE_Y and o.lights[i].y - o.lights[i].range < love.graphics.getHeight() + LOVE_LIGHT_TRANSLATE_Y
then
local lightposrange = {o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, o.lights[i].range}
LOVE_LIGHT_CURRENT = o.lights[i]
LOVE_LIGHT_DIRECTION = LOVE_LIGHT_DIRECTION + 0.002
o.shader:send("lightPosition", {o.lights[i].x - LOVE_LIGHT_TRANSLATE_X, love.graphics.getHeight() - (o.lights[i].y - LOVE_LIGHT_TRANSLATE_Y), o.lights[i].z})
o.shader:send("lightRange", o.lights[i].range)
o.shader:send("lightColor", {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.shader:send("lightSmooth", o.lights[i].smooth)
o.shader:send("lightGlow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength})
o.shader:send("lightAngle", math.pi - o.lights[i].angle / 2.0)
o.shader:send("lightDirection", o.lights[i].direction)
love.graphics.setCanvas(o.lights[i].shadow)
love.graphics.clear()
-- calculate shadows
LOVE_LIGHT_SHADOW_GEOMETRY = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_BODY)
-- draw shadow
love.graphics.setInvertedStencil(stencils.shadow(LOVE_LIGHT_SHADOW_GEOMETRY, LOVE_LIGHT_BODY))
love.graphics.setBlendMode("additive")
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
-- draw color shadows
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
for k = 1,#LOVE_LIGHT_SHADOW_GEOMETRY do
if LOVE_LIGHT_SHADOW_GEOMETRY[k].alpha < 1.0 then
love.graphics.setColor(
LOVE_LIGHT_SHADOW_GEOMETRY[k].red * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[k].alpha),
LOVE_LIGHT_SHADOW_GEOMETRY[k].green * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[k].alpha),
LOVE_LIGHT_SHADOW_GEOMETRY[k].blue * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[k].alpha)
)
love.graphics.polygon("fill", unpack(LOVE_LIGHT_SHADOW_GEOMETRY[k]))
end
end
for k = 1, #LOVE_LIGHT_BODY do
if LOVE_LIGHT_BODY[k].alpha < 1.0 then
love.graphics.setBlendMode("multiplicative")
love.graphics.setColor(LOVE_LIGHT_BODY[k].red, LOVE_LIGHT_BODY[k].green, LOVE_LIGHT_BODY[k].blue)
if LOVE_LIGHT_BODY[k].shadowType == "circle" then
love.graphics.circle("fill", LOVE_LIGHT_BODY[k].x - LOVE_LIGHT_BODY[k].ox, LOVE_LIGHT_BODY[k].y - LOVE_LIGHT_BODY[k].oy, LOVE_LIGHT_BODY[k].radius)
elseif LOVE_LIGHT_BODY[k].shadowType == "rectangle" then
love.graphics.rectangle("fill", LOVE_LIGHT_BODY[k].x - LOVE_LIGHT_BODY[k].ox, LOVE_LIGHT_BODY[k].y - LOVE_LIGHT_BODY[k].oy, LOVE_LIGHT_BODY[k].width, LOVE_LIGHT_BODY[k].height)
elseif LOVE_LIGHT_BODY[k].shadowType == "polygon" then
love.graphics.polygon("fill", unpack(LOVE_LIGHT_BODY[k].data))
end
end
if LOVE_LIGHT_BODY[k].shadowType == "image" and LOVE_LIGHT_BODY[k].img then
love.graphics.setBlendMode("alpha")
local length = 1.0
local shadowRotation = math.atan2((LOVE_LIGHT_BODY[k].x) - o.lights[i].x, (LOVE_LIGHT_BODY[k].y + LOVE_LIGHT_BODY[k].oy) - o.lights[i].y)
--local alpha = math.abs(math.cos(shadowRotation))
LOVE_LIGHT_BODY[k].shadowVert = {
{math.sin(shadowRotation) * LOVE_LIGHT_BODY[k].imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].imgHeight + (math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].shadowY, 0, 0, LOVE_LIGHT_BODY[k].red, LOVE_LIGHT_BODY[k].green, LOVE_LIGHT_BODY[k].blue, LOVE_LIGHT_BODY[k].alpha * LOVE_LIGHT_BODY[k].fadeStrength * 255},
{LOVE_LIGHT_BODY[k].imgWidth + math.sin(shadowRotation) * LOVE_LIGHT_BODY[k].imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].imgHeight + (math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].shadowY, 1, 0, LOVE_LIGHT_BODY[k].red, LOVE_LIGHT_BODY[k].green, LOVE_LIGHT_BODY[k].blue, LOVE_LIGHT_BODY[k].alpha * LOVE_LIGHT_BODY[k].fadeStrength * 255},
{LOVE_LIGHT_BODY[k].imgWidth, LOVE_LIGHT_BODY[k].imgHeight + (math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].shadowY, 1, 1, LOVE_LIGHT_BODY[k].red, LOVE_LIGHT_BODY[k].green, LOVE_LIGHT_BODY[k].blue, LOVE_LIGHT_BODY[k].alpha * 255},
{0, LOVE_LIGHT_BODY[k].imgHeight + (math.cos(shadowRotation) + 1.0) * LOVE_LIGHT_BODY[k].shadowY, 0, 1, LOVE_LIGHT_BODY[k].red, LOVE_LIGHT_BODY[k].green, LOVE_LIGHT_BODY[k].blue, LOVE_LIGHT_BODY[k].alpha * 255}
}
LOVE_LIGHT_BODY[k].shadowMesh:setVertices(LOVE_LIGHT_BODY[k].shadowVert)
love.graphics.draw(LOVE_LIGHT_BODY[k].shadowMesh, LOVE_LIGHT_BODY[k].x - LOVE_LIGHT_BODY[k].ox + LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_BODY[k].y - LOVE_LIGHT_BODY[k].oy + LOVE_LIGHT_TRANSLATE_Y)
end
end
love.graphics.setShader(o.shader)
-- draw shine
love.graphics.setCanvas(o.lights[i].shine)
o.lights[i].shine:clear(255, 255, 255)
love.graphics.setBlendMode("alpha")
love.graphics.setStencil(stencils.poly(LOVE_LIGHT_BODY))
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
lightsOnScreen = lightsOnScreen + 1
o.lights[i].visible = true
else
o.lights[i].visible = false
end
o.lights[i].changed = o.changed
end
end
-- update shadow
love.graphics.setShader()
love.graphics.setCanvas(o.shadow)
love.graphics.setStencil()
love.graphics.setColor(unpack(o.ambient))
love.graphics.setBlendMode("alpha")
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive")
for i = 1, #o.lights do
if o.lights[i].visible then
love.graphics.draw(o.lights[i].shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
end
end
o.isShadowBlur = false
-- update shine
love.graphics.setCanvas(o.shine)
love.graphics.setColor(unpack(o.ambient))
love.graphics.setBlendMode("alpha")
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive")
for i = 1, #o.lights do
if o.lights[i].visible then
love.graphics.draw(o.lights[i].shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
end
end
end
if o.optionPixelShadows and o.isPixelShadows then
-- update pixel shadow
love.graphics.setBlendMode("alpha")
-- create normal map
o.normalMap:clear()
love.graphics.setShader()
love.graphics.setCanvas(o.normalMap)
for i = 1, #o.body do
if o.body[i].type == "image" and o.body[i].normalMesh then
love.graphics.setColor(255, 255, 255)
love.graphics.draw(o.body[i].normalMesh, o.body[i].x - o.body[i].nx + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].ny + LOVE_LIGHT_TRANSLATE_Y)
end
end
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha")
o.pixelShadow2:clear()
love.graphics.setCanvas(o.pixelShadow2)
love.graphics.setBlendMode("additive")
love.graphics.setShader(o.shader2)
for i = 1, #o.lights do
if o.lights[i].visible then
if o.normalInvert then
o.normalInvertShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
o.normalInvertShader:send('lightColor', {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.normalInvertShader:send('lightPosition',{o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, o.lights[i].z / 255.0})
o.normalInvertShader:send('lightRange',{o.lights[i].range})
o.normalInvertShader:send("lightSmooth", o.lights[i].smooth)
o.normalInvertShader:send("lightAngle", math.pi - o.lights[i].angle / 2.0)
o.normalInvertShader:send("lightDirection", o.lights[i].direction)
love.graphics.setShader(o.normalInvertShader)
else
o.normalShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
o.normalShader:send('lightColor', {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.normalShader:send('lightPosition',{o.lights[i].x, love.graphics.getHeight() - o.lights[i].y, o.lights[i].z / 255.0})
o.normalShader:send('lightRange',{o.lights[i].range})
o.normalShader:send("lightSmooth", o.lights[i].smooth)
o.normalShader:send("lightAngle", math.pi - o.lights[i].angle / 2.0)
o.normalShader:send("lightDirection", o.lights[i].direction)
love.graphics.setShader(o.normalShader)
end
love.graphics.draw(o.normalMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
end
end
love.graphics.setShader()
o.pixelShadow:clear(255, 255, 255)
love.graphics.setCanvas(o.pixelShadow)
love.graphics.setBlendMode("alpha")
love.graphics.draw(o.pixelShadow2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("additive")
love.graphics.setColor({o.ambient[1], o.ambient[2], o.ambient[3]})
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setBlendMode("alpha")
end
if o.optionGlow and o.isGlow then
-- create glow map
o.glowMap:clear(0, 0, 0)
love.graphics.setCanvas(o.glowMap)
if o.glowDown then
o.glowTimer = math.max(0.0, o.glowTimer - love.timer.getDelta())
if o.glowTimer == 0.0 then
o.glowDown = not o.glowDown
end
else
o.glowTimer = math.min(o.glowTimer + love.timer.getDelta(), 1.0)
if o.glowTimer == 1.0 then
o.glowDown = not o.glowDown
end
end
for i = 1, #o.body do
if o.body[i].glowStrength > 0.0 then
love.graphics.setColor(o.body[i].glowRed * o.body[i].glowStrength, o.body[i].glowGreen * o.body[i].glowStrength, o.body[i].glowBlue * o.body[i].glowStrength)
else
love.graphics.setColor(0, 0, 0)
end
if o.body[i].type == "circle" then
love.graphics.circle("fill", o.body[i].x, o.body[i].y, o.body[i].radius)
elseif o.body[i].type == "rectangle" then
love.graphics.rectangle("fill", o.body[i].x, o.body[i].y, o.body[i].width, o.body[i].height)
elseif o.body[i].type == "polygon" then
love.graphics.polygon("fill", unpack(o.body[i].data))
elseif o.body[i].type == "image" and o.body[i].img then
if o.body[i].glowStrength > 0.0 and o.body[i].glow then
love.graphics.setShader(o.glowShader)
o.glowShader:send("glowImage", o.body[i].glow)
o.glowShader:send("glowTime", love.timer.getTime() * 0.5)
love.graphics.setColor(255, 255, 255)
else
love.graphics.setShader()
love.graphics.setColor(0, 0, 0)
end
love.graphics.draw(o.body[i].img, o.body[i].x - o.body[i].ix + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].iy + LOVE_LIGHT_TRANSLATE_Y)
end
end
end
if o.optionRefraction and o.isRefraction then
love.graphics.setShader()
-- create refraction map
o.refractionMap:clear()
love.graphics.setCanvas(o.refractionMap)
for i = 1, #o.body do
if o.body[i].refraction and o.body[i].normal then
love.graphics.setColor(255, 255, 255)
if o.body[i].tileX == 0.0 and o.body[i].tileY == 0.0 then
love.graphics.draw(normal, o.body[i].x - o.body[i].nx + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].ny + LOVE_LIGHT_TRANSLATE_Y)
else
o.body[i].normalMesh:setVertices(o.body[i].normalVert)
love.graphics.draw(o.body[i].normalMesh, o.body[i].x - o.body[i].nx + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].ny + LOVE_LIGHT_TRANSLATE_Y)
end
end
end
love.graphics.setColor(0, 0, 0)
for i = 1, #o.body do
if not o.body[i].refractive then
if o.body[i].type == "circle" then
love.graphics.circle("fill", o.body[i].x, o.body[i].y, o.body[i].radius)
elseif o.body[i].type == "rectangle" then
love.graphics.rectangle("fill", o.body[i].x, o.body[i].y, o.body[i].width, o.body[i].height)
elseif o.body[i].type == "polygon" then
love.graphics.polygon("fill", unpack(o.body[i].data))
elseif o.body[i].type == "image" and o.body[i].img then
love.graphics.draw(o.body[i].img, o.body[i].x - o.body[i].ix + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].iy + LOVE_LIGHT_TRANSLATE_Y)
end
end
end
end
if o.optionReflection and o.isReflection then
-- create reflection map
if o.changed then
o.reflectionMap:clear(0, 0, 0)
love.graphics.setCanvas(o.reflectionMap)
for i = 1, #o.body do
if o.body[i].reflection and o.body[i].normal then
love.graphics.setColor(255, 0, 0)
o.body[i].normalMesh:setVertices(o.body[i].normalVert)
love.graphics.draw(o.body[i].normalMesh, o.body[i].x - o.body[i].nx + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].ny + LOVE_LIGHT_TRANSLATE_Y)
end
end
for i = 1, #o.body do
if o.body[i].reflective and o.body[i].img then
love.graphics.setColor(0, 255, 0)
love.graphics.draw(o.body[i].img, o.body[i].x - o.body[i].ix + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].iy + LOVE_LIGHT_TRANSLATE_Y)
elseif not o.body[i].reflection and o.body[i].img then
love.graphics.setColor(0, 0, 0)
love.graphics.draw(o.body[i].img, o.body[i].x - o.body[i].ix + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].iy + LOVE_LIGHT_TRANSLATE_Y)
end
end
end
end
love.graphics.setShader()
love.graphics.setBlendMode("alpha")
love.graphics.setStencil()
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
o.changed = false
end
o.refreshScreenSize = function()
o.shadow = love.graphics.newCanvas()
o.shadow2 = love.graphics.newCanvas()
o.shine = love.graphics.newCanvas()
o.shine2 = love.graphics.newCanvas()
o.normalMap = love.graphics.newCanvas()
o.glowMap = love.graphics.newCanvas()
o.glowMap2 = love.graphics.newCanvas()
o.refractionMap = love.graphics.newCanvas()
o.refractionMap2 = love.graphics.newCanvas()
o.reflectionMap = love.graphics.newCanvas()
o.reflectionMap2 = love.graphics.newCanvas()
o.pixelShadow = love.graphics.newCanvas()
o.pixelShadow2 = love.graphics.newCanvas()
end
-- draw shadow
o.drawShadow = function()
if o.optionShadows and (o.isShadows or o.isLight) then
love.graphics.setColor(255, 255, 255)
if o.blur then
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
LOVE_LIGHT_BLURV:send("steps", o.blur)
LOVE_LIGHT_BLURH:send("steps", o.blur)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.shadow2)
love.graphics.setShader(LOVE_LIGHT_BLURV)
love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(o.shadow)
love.graphics.setShader(LOVE_LIGHT_BLURH)
love.graphics.draw(o.shadow2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
else
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
love.graphics.draw(o.shadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
end
end
end
-- draw shine
o.drawShine = function()
if o.optionShadows and o.isShadows then
love.graphics.setColor(255, 255, 255)
if o.blur and false then
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
LOVE_LIGHT_BLURV:send("steps", o.blur)
LOVE_LIGHT_BLURH:send("steps", o.blur)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.shine2)
love.graphics.setShader(LOVE_LIGHT_BLURV)
love.graphics.draw(o.shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(o.shine)
love.graphics.setShader(LOVE_LIGHT_BLURH)
love.graphics.draw(o.shine2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
love.graphics.draw(o.shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
else
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
love.graphics.draw(o.shine, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
end
end
end
-- draw pixel shadow
o.drawPixelShadow = function()
if o.optionPixelShadows and o.isPixelShadows then
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative")
love.graphics.setShader()
love.graphics.draw(o.pixelShadow, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
end
end
-- draw material
o.drawMaterial = function()
love.graphics.setShader(o.materialShader)
for i = 1, #o.body do
if o.body[i].material and o.body[i].normal then
love.graphics.setColor(255, 255, 255)
o.materialShader:send("material", o.body[i].material)
love.graphics.draw(o.body[i].normal, o.body[i].x - o.body[i].nx + LOVE_LIGHT_TRANSLATE_X, o.body[i].y - o.body[i].ny + LOVE_LIGHT_TRANSLATE_Y)
end
end
love.graphics.setShader()
end
-- draw glow
o.drawGlow = function()
if o.optionGlow and o.isGlow then
love.graphics.setColor(255, 255, 255)
if o.glowBlur == 0.0 then
love.graphics.setBlendMode("additive")
love.graphics.setShader()
love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
else
LOVE_LIGHT_BLURV:send("steps", o.glowBlur)
LOVE_LIGHT_BLURH:send("steps", o.glowBlur)
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
love.graphics.setBlendMode("additive")
o.glowMap2:clear()
love.graphics.setCanvas(o.glowMap2)
love.graphics.setShader(LOVE_LIGHT_BLURV)
love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(o.glowMap)
love.graphics.setShader(LOVE_LIGHT_BLURH)
love.graphics.draw(o.glowMap2, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
love.graphics.setShader()
love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setBlendMode("alpha")
end
end
end
-- draw refraction
o.drawRefraction = function()
if o.optionRefraction and o.isRefraction then
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
if LOVE_LIGHT_LAST_BUFFER then
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.refractionMap2)
love.graphics.draw(LOVE_LIGHT_LAST_BUFFER, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
o.refractionShader:send("backBuffer", o.refractionMap2)
o.refractionShader:send("refractionStrength", o.refractionStrength)
love.graphics.setShader(o.refractionShader)
love.graphics.draw(o.refractionMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setShader()
end
end
end
-- draw reflection
o.drawReflection = function()
if o.optionReflection and o.isReflection then
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
if LOVE_LIGHT_LAST_BUFFER then
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(o.reflectionMap2)
love.graphics.draw(LOVE_LIGHT_LAST_BUFFER, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
o.reflectionShader:send("backBuffer", o.reflectionMap2)
o.reflectionShader:send("reflectionStrength", o.reflectionStrength)
o.reflectionShader:send("reflectionVisibility", o.reflectionVisibility)
love.graphics.setShader(o.reflectionShader)
love.graphics.draw(o.reflectionMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y)
love.graphics.setShader()
end
end
end
-- new light
o.newLight = function(x, y, red, green, blue, range)
o.lights[#o.lights + 1] = Light(o, x, y, red, green, blue, range)
o.isLight = true
return o.lights[#o.lights]
end
-- clear lights
o.clearLights = function()
o.lights = {}
o.isLight = false
o.changed = true
end
-- clear objects
o.clearBodys = function()
o.body = {}
o.changed = true
o.isShadows = false
o.isPixelShadows = false
o.isGlow = false
o.isRefraction = false
o.isReflection = false
end
-- set offset
o.setTranslation = function(translateX, translateY)
LOVE_LIGHT_TRANSLATE_X = translateX
LOVE_LIGHT_TRANSLATE_Y = translateY
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 normal invert
o.setNormalInvert = function(invert)
o.normalInvert = invert
end
-- set blur
o.setBlur = function(blur)
o.blur = blur
o.changed = true
end
-- set blur
o.setShadowBlur = function(blur)
o.blur = blur
o.changed = true
end
-- set buffer
o.setBuffer = function(buffer)
if buffer == "render" then
love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER)
else
LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas()
end
if buffer == "glow" then
love.graphics.setCanvas(o.glowMap)
end
end
-- set glow blur
o.setGlowStrength = function(strength)
o.glowBlur = strength
o.changed = true
end
-- set refraction blur
o.setRefractionStrength = function(strength)
o.refractionStrength = strength
end
-- set reflection strength
o.setReflectionStrength = function(strength)
o.reflectionStrength = strength
end
-- set reflection visibility
o.setReflectionVisibility = function(visibility)
o.reflectionVisibility = visibility
end
-- new rectangle
o.newRectangle = function(x, y, w, h)
return o.newBody("rectangle", x, y, width, height)
end
-- new circle
o.newCircle = function(x, y, r)
return o.newBody("circle", x, y, radius)
end
-- new polygon
o.newPolygon = function(...)
return o.newBody("polygon", ...)
end
-- new image
o.newImage = function(img, x, y, width, height, ox, oy)
return o.newBody("image", img, x, y, width, height, ox, oy)
end
-- new refraction
o.newRefraction = function(normal, x, y, width, height)
return o.newBody("refraction", normal, x, y, width, height)
end
-- new refraction from height map
o.newRefractionHeightMap = function(heightMap, x, y, strength)
local normal = HeightMapToNormalMap(heightMap, strength)
return o.newRefraction(p, normal, x, y)
end
-- new reflection
o.newReflection = function(normal, x, y, width, height)
return o.newBody("reflection", normal, x, y, width, height)
end
-- new reflection from height map
o.newReflectionHeightMap = function(heightMap, x, y, strength)
local normal = HeightMapToNormalMap(heightMap, strength)
return o.newReflection(p, normal, x, y)
end
-- new body
o.newBody = function(type, ...)
local id = #o.body + 1
o.body[id] = Body(o, id, type, ...)
o.changed = true
return o.body[#o.body]
end
-- set polygon data
o.setPoints = function(n, ...)
o.body[n].data = {...}
end
-- get polygon count
o.getBodyCount = function()
return #o.body
end
-- get polygon
o.getPoints = function(n)
if o.body[n].data then
return unpack(o.body[n].data)
end
end
-- set light position
o.setLightPosition = function(n, x, y, z)
o.lights[n]:setPosition(x, y, z)
end
-- set light x
o.setLightX = function(n, x)
o.lights[n]:setX(x)
end
-- set light y
o.setLightY = function(n, y)
o.lights[n]:setY(y)
end
-- set light angle
o.setLightAngle = function(n, angle)
o.lights[n]:setAngle(angle)
end
-- set light direction
o.setLightDirection = function(n, direction)
o.lights[n]:setDirection(direction)
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
-- get type
o.getType = function()
return "world"
end
return o
end
function calculateShadows(light, body)
local shadowGeometry = {}
local shadowLength = 100000
for i = 1, #body do
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then
curPolygon = body[i].data
if not body[i].castsNoShadow then
local edgeFacingTo = {}
for k = 1, #curPolygon, 2 do
local indexOfNextVertex = (k + 2) % #curPolygon
local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[k + 1], curPolygon[indexOfNextVertex] - curPolygon[k]}
local lightToPoint = {curPolygon[k] - light.x, curPolygon[k + 1] - light.y}
normal = vector.normalize(normal)
lightToPoint = vector.normalize(lightToPoint)
local dotProduct = vector.dot(normal, lightToPoint)
if dotProduct > 0 then table.insert(edgeFacingTo, true)
else table.insert(edgeFacingTo, false) end
end
local curShadowGeometry = {}
for k = 1, #edgeFacingTo do
local nextIndex = (k + 1) % #edgeFacingTo
if nextIndex == 0 then nextIndex = #edgeFacingTo end
if edgeFacingTo[k] and not edgeFacingTo[nextIndex] then
curShadowGeometry[1] = curPolygon[nextIndex*2-1]
curShadowGeometry[2] = curPolygon[nextIndex*2]
local lightVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y})
curShadowGeometry[3] = curShadowGeometry[1] + lightVecFrontBack[1] * shadowLength
curShadowGeometry[4] = curShadowGeometry[2] + lightVecFrontBack[2] * shadowLength
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
curShadowGeometry[7] = curPolygon[nextIndex*2-1]
curShadowGeometry[8] = curPolygon[nextIndex*2]
local lightVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.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
curShadowGeometry.alpha = body[i].alpha
curShadowGeometry.red = body[i].red
curShadowGeometry.green = body[i].green
curShadowGeometry.blue = body[i].blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
end
end
elseif body[i].shadowType == "circle" then
if not body[i].castsNoShadow then
local length = math.sqrt(math.pow(light.x - (body[i].x - body[i].ox), 2) + math.pow(light.y - (body[i].y - body[i].oy), 2))
if length >= body[i].radius and length <= light.range then
local curShadowGeometry = {}
local angle = math.atan2(light.x - (body[i].x - body[i].ox), (body[i].y - body[i].oy) - light.y) + math.pi / 2
local x2 = ((body[i].x - body[i].ox) + math.sin(angle) * body[i].radius)
local y2 = ((body[i].y - body[i].oy) - math.cos(angle) * body[i].radius)
local x3 = ((body[i].x - body[i].ox) - math.sin(angle) * body[i].radius)
local y3 = ((body[i].y - body[i].oy) + math.cos(angle) * body[i].radius)
curShadowGeometry[1] = x2
curShadowGeometry[2] = y2
curShadowGeometry[3] = x3
curShadowGeometry[4] = y3
curShadowGeometry[5] = x3 - (light.x - x3) * shadowLength
curShadowGeometry[6] = y3 - (light.y - y3) * shadowLength
curShadowGeometry[7] = x2 - (light.x - x2) * shadowLength
curShadowGeometry[8] = y2 - (light.y - y2) * shadowLength
curShadowGeometry.alpha = body[i].alpha
curShadowGeometry.red = body[i].red
curShadowGeometry.green = body[i].green
curShadowGeometry.blue = body[i].blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
end
end
end
end
return shadowGeometry
end
function HeightMapToNormalMap(heightMap, strength)
local imgData = heightMap:getData()
local imgData2 = love.image.newImageData(heightMap:getWidth(), heightMap:getHeight())
local red, green, blue, alpha
local x, y
local matrix = {}
matrix[1] = {}
matrix[2] = {}
matrix[3] = {}
strength = strength or 1.0
for i = 0, heightMap:getHeight() - 1 do
for k = 0, heightMap:getWidth() - 1 do
for l = 1, 3 do
for m = 1, 3 do
if k + (l - 1) < 1 then
x = heightMap:getWidth() - 1
elseif k + (l - 1) > heightMap:getWidth() - 1 then
x = 1
else
x = k + l - 1
end
if i + (m - 1) < 1 then
y = heightMap:getHeight() - 1
elseif i + (m - 1) > heightMap:getHeight() - 1 then
y = 1
else
y = i + m - 1
end
local red, green, blue, alpha = imgData:getPixel(x, y)
matrix[l][m] = red
end
end
red = (255 + ((matrix[1][2] - matrix[2][2]) + (matrix[2][2] - matrix[3][2])) * strength) / 2.0
green = (255 + ((matrix[2][2] - matrix[1][1]) + (matrix[2][3] - matrix[2][2])) * strength) / 2.0
blue = 192
imgData2:setPixel(k, i, red, green, blue)
end
end
return love.graphics.newImage(imgData2)
end

44
lib/stencils.lua Normal file
View File

@ -0,0 +1,44 @@
local stencils = {}
function stencils.shadow(geometry, bodies)
return function()
for i = 1,#geometry do
if geometry[i].alpha == 1.0 then
love.graphics.polygon("fill", unpack(geometry[i]))
end
end
for i = 1, #bodies do
if not bodies[i].castsNoShadow then
if bodies[i].shadowType == "circle" then
love.graphics.circle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].radius)
elseif bodies[i].shadowType == "rectangle" then
love.graphics.rectangle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].width, bodies[i].height)
elseif bodies[i].shadowType == "polygon" then
love.graphics.polygon("fill", unpack(bodies[i].data))
elseif bodies[i].shadowType == "image" then
--love.graphics.rectangle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].width, bodies[i].height)
end
end
end
end
end
function stencils.poly(bodies)
return function()
for i = 1, #bodies do
if bodies[i].shine and (bodies[i].glowStrength == 0.0 or (bodies[i].type == "image" and not bodies[i].normal)) then
if bodies[i].shadowType == "circle" then
love.graphics.circle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].radius)
elseif bodies[i].shadowType == "rectangle" then
love.graphics.rectangle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].width, bodies[i].height)
elseif bodies[i].shadowType == "polygon" then
love.graphics.polygon("fill", unpack(bodies[i].data))
elseif bodies[i].shadowType == "image" then
--love.graphics.rectangle("fill", bodies[i].x - bodies[i].ox, bodies[i].y - bodies[i].oy, bodies[i].width, bodies[i].height)
end
end
end
end
end
return stencils

21
lib/vector.lua Normal file
View File

@ -0,0 +1,21 @@
local vector = {}
-- vector functions
function vector.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 vector.dot(v1, v2)
return v1[1] * v2[1] + v1[2] * v2[2]
end
function vector.lengthSqr(v)
return v[1] * v[1] + v[2] * v[2]
end
function vector.length(v)
return math.sqrt(lengthSqr(v))
end
return vector

View File

@ -7,7 +7,7 @@
-- Updated by Dresenpai
require "lib/postshader"
require "lib/light"
require "lib/light_world"
exf = {}
exf.current = nil
@ -54,7 +54,7 @@ function exf.empty() end
function exf.update(dt)
exf.list:update(dt)
lightMouse.setPosition(love.mouse.getX(), love.mouse.getY())
lightMouse:setPosition(love.mouse.getX(), love.mouse.getY())
end
function exf.draw()
@ -184,7 +184,7 @@ function exf.resume()
-- create light
lightMouse = lightWorld.newLight(0, 0, 255, 127, 63, 500)
lightMouse.setSmooth(2)
lightMouse:setSmooth(2)
-- create shadow bodys
circleTest = lightWorld.newCircle(800 - 128, 600 - 128, 46)