singled out the drawing into one function with background and foreground callbacks, this will draw the refraction and reflection without the post shader

This commit is contained in:
Tim Anema 2014-10-02 20:32:31 -04:00
parent 6739da8423
commit 3d15d0832e
6 changed files with 248 additions and 329 deletions

View File

@ -89,10 +89,15 @@ function love.load()
-- light world -- light world
lightRange = 400 lightRange = 400
lightSmooth = 1.0 lightSmooth = 1.0
lightWorld = LightWorld()
lightWorld:setAmbientColor(15, 15, 31) lightWorld = LightWorld({
lightWorld:setRefractionStrength(16.0) ambient = {15,15,15},
lightWorld:setReflectionVisibility(0.75) refractionStrength = 16.0,
reflectionVisibility = 0.75,
drawBackground = drawBackground,
drawForground = drawForground
})
mouseLight = lightWorld:newLight(0, 0, 255, 191, 127, lightRange) mouseLight = lightWorld:newLight(0, 0, 255, 191, 127, lightRange)
mouseLight:setGlowStrength(0.3) mouseLight:setGlowStrength(0.3)
mouseLight:setSmooth(lightSmooth) mouseLight:setSmooth(lightSmooth)
@ -224,95 +229,12 @@ function love.update(dt)
end end
function love.draw() function love.draw()
lightWorld:update()
-- set shader buffer -- set shader buffer
if bloomOn then if bloomOn then
love.postshader.setBuffer("render") love.postshader.setBuffer("render")
end end
love.graphics.setBlendMode("alpha") lightWorld:draw()
if normalOn then
love.graphics.setColor(127, 127, 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
else
love.graphics.setColor(255, 255, 255)
if textureOn then
love.graphics.draw(imgFloor, quadScreen, offsetX % 32 - 32, offsetY % 24 - 24)
else
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
end
end
for i = 1, phyCnt do
if phyLight[i]:getType() == "refraction" then
if not normalOn then
--if math.mod(i, 2) == 0 then
love.graphics.setBlendMode("alpha")
love.graphics.setColor(255, 255, 255, 191)
love.graphics.draw(water, phyLight[i].x - phyLight[i].ox, phyLight[i].y - phyLight[i].oy)
--else
--love.graphics.setBlendMode("multiplicative")
--math.randomseed(i)
--love.graphics.setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
--love.graphics.rectangle("fill", phyLight[i].x - phyLight[i].ox, phyLight[i].y - phyLight[i].oy, 128, 128)
--end
end
end
end
-- draw lightmap shadows
if lightOn and not normalOn then
lightWorld:drawShadow()
end
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())
end
end
-- draw lightmap shine
if lightOn and not normalOn then
lightWorld:drawShine()
end
love.graphics.setBlendMode("alpha")
for i = 1, phyCnt do
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)
elseif not phyLight[i].material then
math.randomseed(i)
love.graphics.setColor(math.random(127, 255), math.random(127, 255), math.random(127, 255))
love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ix, phyLight[i].y - phyLight[i].iy)
end
end
end
if not normalOn then
lightWorld:drawMaterial()
end
-- draw pixel shadow
if lightOn and not normalOn then
lightWorld:drawPixelShadow()
end
-- draw glow
if lightOn and not normalOn then
lightWorld:drawGlow()
end
-- draw reflection
lightWorld:drawReflection()
-- draw refraction
lightWorld:drawRefraction()
love.graphics.draw(imgLight, mx - 5, (my - 5) - (16.0 + (math.sin(lightDirection) + 1.0) * 64.0)) love.graphics.draw(imgLight, mx - 5, (my - 5) - (16.0 + (math.sin(lightDirection) + 1.0) * 64.0))
@ -432,6 +354,61 @@ function love.draw()
love.postshader.draw() love.postshader.draw()
end end
function drawBackground(l,t,w,h)
love.graphics.setBlendMode("alpha")
if normalOn then
love.graphics.setColor(127, 127, 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
else
love.graphics.setColor(255, 255, 255)
if textureOn then
love.graphics.draw(imgFloor, quadScreen, offsetX % 32 - 32, offsetY % 24 - 24)
else
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
end
end
for i = 1, phyCnt do
if phyLight[i]:getType() == "refraction" then
if not normalOn then
love.graphics.setBlendMode("alpha")
love.graphics.setColor(255, 255, 255, 191)
love.graphics.draw(water, phyLight[i].x - phyLight[i].ox, phyLight[i].y - phyLight[i].oy)
end
end
end
end
function drawForground(l,t,w,h)
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())
end
end
love.graphics.setBlendMode("alpha")
for i = 1, phyCnt do
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)
elseif not phyLight[i].material then
math.randomseed(i)
love.graphics.setColor(math.random(127, 255), math.random(127, 255), math.random(127, 255))
love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ix, phyLight[i].y - phyLight[i].iy)
end
end
end
if not normalOn then
lightWorld:drawMaterial(l,t,w,h)
end
end
function love.mousepressed(x, y, c) function love.mousepressed(x, y, c)
if c == "m" then if c == "m" then
-- add light -- add light

View File

@ -1,6 +1,5 @@
require 'lib/postshader'
-- Example: Short Example -- Example: Short Example
require "lib/postshader"
local gamera = require "vendor/gamera" local gamera = require "vendor/gamera"
local LightWorld = require "lib/light_world" local LightWorld = require "lib/light_world"
@ -14,14 +13,16 @@ function love.load()
glow = love.graphics.newImage("gfx/machine2_glow.png") glow = love.graphics.newImage("gfx/machine2_glow.png")
-- create light world -- create light world
lightWorld = LightWorld() lightWorld = LightWorld({
drawBackground = drawBackground,
drawForground = drawForground
})
lightWorld:setAmbientColor(15, 15, 31) lightWorld:setAmbientColor(15, 15, 31)
lightWorld:setRefractionStrength(32.0) lightWorld:setRefractionStrength(32.0)
-- create light -- create light
lightMouse = lightWorld:newLight(0, 0, 255, 127, 63, 300) lightMouse = lightWorld:newLight(0, 0, 255, 127, 63, 300)
lightMouse:setGlowStrength(0.3) lightMouse:setGlowStrength(0.3)
--lightMouse:setSmooth(0.01)
-- create shadow bodys -- create shadow bodys
circleTest = lightWorld:newCircle(256, 256, 16) circleTest = lightWorld:newCircle(256, 256, 16)
@ -34,15 +35,7 @@ function love.load()
-- create body object -- create body object
objectTest = lightWorld:newRefraction(normal, 64, 64, 128, 128) objectTest = lightWorld:newRefraction(normal, 64, 64, 128, 128)
--objectTest:setShine(false)
--objectTest:setShadowType("rectangle")
--objectTest:setShadowDimension(64, 64)
objectTest:setReflection(true) objectTest:setReflection(true)
-- set background
quadScreen = love.graphics.newQuad(0, 0, love.window.getWidth(), love.window.getHeight(), 32, 24)
imgFloor = love.graphics.newImage("gfx/floor.png")
imgFloor:setWrap("repeat", "repeat")
end end
function love.update(dt) function love.update(dt)
@ -74,19 +67,20 @@ end
function love.draw() function love.draw()
camera:draw(function(l,t,w,h) camera:draw(function(l,t,w,h)
lightWorld:update(l,t,w,h) lightWorld:draw(l,t,w,h,scale)
end)
end
function drawBackground(l,t,w,h)
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.rectangle("fill", 0, 0, 2000, 2000) love.graphics.rectangle("fill", 0, 0, 2000, 2000)
lightWorld:drawShadow(l,t,w,h) end
function drawForground(l,t,w,h)
love.graphics.setColor(63, 255, 127) love.graphics.setColor(63, 255, 127)
love.graphics.circle("fill", circleTest:getX(), circleTest:getY(), circleTest:getRadius()) love.graphics.circle("fill", circleTest:getX(), circleTest:getY(), circleTest:getRadius())
love.graphics.polygon("fill", rectangleTest:getPoints()) love.graphics.polygon("fill", rectangleTest:getPoints())
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.draw(image, 64 - image:getWidth() * 0.5, 64 - image:getHeight() * 0.5) love.graphics.draw(image, 64 - image:getWidth() * 0.5, 64 - image:getHeight() * 0.5)
lightWorld:drawShine(l,t,w,h)
lightWorld:drawPixelShadow(l,t,w,h)
lightWorld:drawGlow(l,t,w,h)
lightWorld:drawRefraction(l,t,w,h)
lightWorld:drawReflection(l,t,w,h)
end)
end end

View File

@ -7,14 +7,13 @@ local body = class()
body.glowShader = love.graphics.newShader(_PACKAGE.."/shaders/glow.glsl") body.glowShader = love.graphics.newShader(_PACKAGE.."/shaders/glow.glsl")
body.materialShader = love.graphics.newShader(_PACKAGE.."/shaders/material.glsl") body.materialShader = love.graphics.newShader(_PACKAGE.."/shaders/material.glsl")
function body:init(world, id, type, ...) function body:init(id, type, ...)
local args = {...} local args = {...}
self.id = id self.id = id
self.type = type self.type = type
self.normal = nil self.normal = nil
self.material = nil self.material = nil
self.glow = nil self.glow = nil
self.world = world
self.shine = true self.shine = true
self.red = 0 self.red = 0
@ -35,7 +34,6 @@ function body:init(world, id, type, ...)
self.ox = args[4] or 0 self.ox = args[4] or 0
self.oy = args[5] or 0 self.oy = args[5] or 0
self.shadowType = "circle" self.shadowType = "circle"
world.isShadows = true
elseif self.type == "rectangle" then elseif self.type == "rectangle" then
self.x = args[1] or 0 self.x = args[1] or 0
self.y = args[2] or 0 self.y = args[2] or 0
@ -54,11 +52,9 @@ function body:init(world, id, type, ...)
self.x - self.ox, self.x - self.ox,
self.y - self.oy + self.height self.y - self.oy + self.height
} }
world.isShadows = true
elseif self.type == "polygon" then elseif self.type == "polygon" then
self.shadowType = "polygon" self.shadowType = "polygon"
self.data = args or {0, 0, 0, 0, 0, 0} self.data = args or {0, 0, 0, 0, 0, 0}
world.isShadows = true
elseif self.type == "image" then elseif self.type == "image" then
self.img = args[1] self.img = args[1]
self.x = args[2] or 0 self.x = args[2] or 0
@ -95,7 +91,6 @@ function body:init(world, id, type, ...)
self.y - self.oy + self.height self.y - self.oy + self.height
} }
self.reflective = true self.reflective = true
world.isShadows = true
elseif self.type == "refraction" then elseif self.type == "refraction" then
self.normal = args[1] self.normal = args[1]
self.x = args[2] or 0 self.x = args[2] or 0
@ -122,7 +117,6 @@ function body:init(world, id, type, ...)
self.ox = self.width * 0.5 self.ox = self.width * 0.5
self.oy = self.height * 0.5 self.oy = self.height * 0.5
self.refraction = true self.refraction = true
world.isRefraction = true
elseif self.type == "reflection" then elseif self.type == "reflection" then
self.normal = args[1] self.normal = args[1]
self.x = args[2] or 0 self.x = args[2] or 0
@ -149,7 +143,6 @@ function body:init(world, id, type, ...)
self.ox = self.width * 0.5 self.ox = self.width * 0.5
self.oy = self.height * 0.5 self.oy = self.height * 0.5
self.reflection = true self.reflection = true
world.isReflection = true
end end
end end
@ -173,7 +166,6 @@ function body:setPosition(x, y)
self.x = x self.x = x
self.y = y self.y = y
self:refresh() self:refresh()
self.world.changed = true
end end
end end
@ -182,7 +174,6 @@ function body:setX(x)
if x ~= self.x then if x ~= self.x then
self.x = x self.x = x
self:refresh() self:refresh()
self.world.changed = true
end end
end end
@ -191,7 +182,6 @@ function body:setY(y)
if y ~= self.y then if y ~= self.y then
self.y = y self.y = y
self:refresh() self:refresh()
self.world.changed = true
end end
end end
@ -230,7 +220,6 @@ function body:setDimension(width, height)
self.width = width self.width = width
self.height = height self.height = height
self:refresh() self:refresh()
self.world.changed = true
end end
-- set offset -- set offset
@ -241,7 +230,6 @@ function body:setOffset(ox, oy)
if self.shadowType == "rectangle" then if self.shadowType == "rectangle" then
self:refresh() self:refresh()
end end
self.world.changed = true
end end
end end
@ -251,7 +239,6 @@ function body:setImageOffset(ix, iy)
self.ix = ix self.ix = ix
self.iy = iy self.iy = iy
self:refresh() self:refresh()
self.world.changed = true
end end
end end
@ -261,7 +248,6 @@ function body:setNormalOffset(nx, ny)
self.nx = nx self.nx = nx
self.ny = ny self.ny = ny
self:refresh() self:refresh()
self.world.changed = true
end end
end end
@ -270,13 +256,11 @@ function body:setGlowColor(red, green, blue)
self.glowRed = red self.glowRed = red
self.glowGreen = green self.glowGreen = green
self.glowBlue = blue self.glowBlue = blue
self.world.changed = true
end end
-- set glow alpha -- set glow alpha
function body:setGlowStrength(strength) function body:setGlowStrength(strength)
self.glowStrength = strength self.glowStrength = strength
self.world.changed = true
end end
-- get radius -- get radius
@ -288,14 +272,12 @@ end
function body:setRadius(radius) function body:setRadius(radius)
if radius ~= self.radius then if radius ~= self.radius then
self.radius = radius self.radius = radius
self.world.changed = true
end end
end end
-- set polygon data -- set polygon data
function body:setPoints(...) function body:setPoints(...)
self.data = {...} self.data = {...}
self.world.changed = true
end end
-- get polygon data -- get polygon data
@ -306,13 +288,11 @@ end
-- set shadow on/off -- set shadow on/off
function body:setShadow(b) function body:setShadow(b)
self.castsNoShadow = not b self.castsNoShadow = not b
self.world.changed = true
end end
-- set shine on/off -- set shine on/off
function body:setShine(b) function body:setShine(b)
self.shine = b self.shine = b
self.world.changed = true
end end
-- set glass color -- set glass color
@ -320,13 +300,11 @@ function body:setColor(red, green, blue)
self.red = red self.red = red
self.green = green self.green = green
self.blue = blue self.blue = blue
self.world.changed = true
end end
-- set glass alpha -- set glass alpha
function body:setAlpha(alpha) function body:setAlpha(alpha)
self.alpha = alpha self.alpha = alpha
self.world.changed = true
end end
-- set reflection on/off -- set reflection on/off
@ -376,8 +354,6 @@ function body:setNormalMap(normal, width, height, nx, ny)
{0.0, self.normalHeight, 0.0, 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.normalMesh = love.graphics.newMesh(self.normalVert, self.normal, "fan")
self.world.isPixelShadows = true
else else
self.normalMesh = nil self.normalMesh = nil
end end
@ -475,8 +451,6 @@ end
function body:setGlowMap(glow) function body:setGlowMap(glow)
self.glow = glow self.glow = glow
self.glowStrength = 1.0 self.glowStrength = 1.0
self.world.isGlow = true
end end
-- set tile offset -- set tile offset
@ -489,7 +463,6 @@ function body:setNormalTileOffset(tx, ty)
{self.normalWidth, self.normalHeight, self.tileX + 1.0, self.tileY + 1.0}, {self.normalWidth, self.normalHeight, self.tileX + 1.0, self.tileY + 1.0},
{0.0, self.normalHeight, self.tileX, self.tileY + 1.0} {0.0, self.normalHeight, self.tileX, self.tileY + 1.0}
} }
self.world.changed = true
end end
-- get type -- get type

View File

@ -9,13 +9,10 @@ light.shader = love.graphics.newShader(_PACKAGE.."/shaders/poly_shad
light.normalShader = love.graphics.newShader(_PACKAGE.."/shaders/normal.glsl") light.normalShader = love.graphics.newShader(_PACKAGE.."/shaders/normal.glsl")
light.normalInvertShader = love.graphics.newShader(_PACKAGE.."/shaders/normal_invert.glsl") light.normalInvertShader = love.graphics.newShader(_PACKAGE.."/shaders/normal_invert.glsl")
function light:init(world, x, y, r, g, b, range) function light:init(x, y, r, g, b, range)
self.world = world
self.direction = 0 self.direction = 0
self.angle = math.pi * 2.0 self.angle = math.pi * 2.0
self.range = 0 self.range = 0
self.shadow = love.graphics.newCanvas()
self.shine = love.graphics.newCanvas()
self.x = x or 0 self.x = x or 0
self.y = y or 0 self.y = y or 0
self.z = 15 self.z = 15
@ -27,6 +24,12 @@ function light:init(world, x, y, r, g, b, range)
self.glowSize = 0.1 self.glowSize = 0.1
self.glowStrength = 0.0 self.glowStrength = 0.0
self.visible = true self.visible = true
self:refresh()
end
function light:refresh()
self.shadow = love.graphics.newCanvas()
self.shine = love.graphics.newCanvas()
end end
-- set position -- set position
@ -63,6 +66,7 @@ function light:setY(y)
self.y = y self.y = y
end end
end end
-- set color -- set color
function light:setColor(red, green, blue) function light:setColor(red, green, blue)
self.red = red self.red = red
@ -118,7 +122,7 @@ function light:setGlowStrength(strength)
self.glowStrength = strength self.glowStrength = strength
end end
function light:updateShadow(l,t,w,h) function light:updateShadow(l,t,w,h, bodies)
love.graphics.setShader(self.shader) love.graphics.setShader(self.shader)
if self.x + self.range > l and self.x - self.range < (l+w) and self.y + self.range > t and self.y - self.range < (t+h) then if self.x + self.range > l and self.x - self.range < (l+w) and self.y + self.range > t and self.y - self.range < (t+h) then
local lightposrange = {self.x, h - self.y, self.range} local lightposrange = {self.x, h - self.y, self.range}
@ -134,10 +138,10 @@ function light:updateShadow(l,t,w,h)
love.graphics.clear() love.graphics.clear()
-- calculate shadows -- calculate shadows
local shadow_geometry = self:calculateShadows() local shadow_geometry = self:calculateShadows(bodies)
-- draw shadow -- draw shadow
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body)) love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, bodies))
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.rectangle("fill", l,t,w,h) love.graphics.rectangle("fill", l,t,w,h)
@ -155,8 +159,8 @@ function light:updateShadow(l,t,w,h)
end end
end end
for k = 1, #self.world.body do for k = 1, #bodies do
self.world.body[k]:drawShadow(self, l,t,w,h) bodies[k]:drawShadow(self, l,t,w,h)
end end
love.graphics.setShader(self.shader) love.graphics.setShader(self.shader)
@ -165,10 +169,9 @@ function light:updateShadow(l,t,w,h)
love.graphics.setCanvas(self.shine) love.graphics.setCanvas(self.shine)
self.shine:clear(255, 255, 255) self.shine:clear(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setStencil(stencils.poly(self.world.body)) love.graphics.setStencil(stencils.poly(bodies))
-- WHOA THIS MAY BE THE ISSUE HERE FIND THIS!
love.graphics.rectangle("fill", l,t,w,h) love.graphics.rectangle("fill", l,t,w,h)
love.graphics.setStencil()
self.visible = true self.visible = true
else else
self.visible = false self.visible = false
@ -178,6 +181,8 @@ end
function light:drawShadow(l,t,w,h) function light:drawShadow(l,t,w,h)
if self.visible then if self.visible then
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive")
love.graphics.draw(self.shadow, l, t) love.graphics.draw(self.shadow, l, t)
end end
end end
@ -189,16 +194,15 @@ function light:drawShine(l,t,w,h)
end end
local shadowLength = 100000 local shadowLength = 100000
function light:calculateShadows() function light:calculateShadows(bodies)
local shadowGeometry = {} local shadowGeometry = {}
local body = self.world.body
for i = 1, #body do for i = 1, #bodies do
local current local current
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then if bodies[i].shadowType == "rectangle" or bodies[i].shadowType == "polygon" then
current = self:calculatePolyShadow(body[i]) current = self:calculatePolyShadow(bodies[i])
elseif body[i].shadowType == "circle" then elseif bodies[i].shadowType == "circle" then
current = self:calculateCircleShadow(body[i]) current = self:calculateCircleShadow(bodies[i])
end end
if current ~= nil then if current ~= nil then
shadowGeometry[#shadowGeometry + 1] = current shadowGeometry[#shadowGeometry + 1] = current
@ -300,7 +304,7 @@ function light:calculateCircleShadow(circle)
end end
end end
function light:drawPixelShadow(l,t,w,h) function light:drawPixelShadow(l,t,w,h, normalMap)
if self.visible then if self.visible then
if self.normalInvert then if self.normalInvert then
self.normalInvertShader:send('screenResolution', {w, h}) self.normalInvertShader:send('screenResolution', {w, h})
@ -321,7 +325,7 @@ function light:drawPixelShadow(l,t,w,h)
self.normalShader:send("lightDirection", self.direction) self.normalShader:send("lightDirection", self.direction)
love.graphics.setShader(self.normalShader) love.graphics.setShader(self.normalShader)
end end
love.graphics.draw(self.world.normalMap, l, t) love.graphics.draw(normalMap, l, t)
end end
end end

View File

@ -34,81 +34,72 @@ light_world.blurh = love.graphics.newShader(_PACKAGE.."/shaders/blu
light_world.refractionShader = love.graphics.newShader(_PACKAGE.."/shaders/refraction.glsl") light_world.refractionShader = love.graphics.newShader(_PACKAGE.."/shaders/refraction.glsl")
light_world.reflectionShader = love.graphics.newShader(_PACKAGE.."/shaders/reflection.glsl") light_world.reflectionShader = love.graphics.newShader(_PACKAGE.."/shaders/reflection.glsl")
light_world.blurv:send("screen", {love.window.getWidth(), love.window.getHeight()}) function light_world:init(options)
light_world.blurh:send("screen", {love.window.getWidth(), love.window.getHeight()})
light_world.refractionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
light_world.reflectionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
function light_world:init()
self.last_buffer = nil
self.lights = {} self.lights = {}
self.body = {} self.body = {}
self.ambient = {0, 0, 0} self.ambient = {0, 0, 0}
self.normalInvert = false self.normalInvert = false
self.glowBlur = 1.0
self.glowTimer = 0.0
self.glowDown = false
self.refractionStrength = 8.0 self.refractionStrength = 8.0
self.reflectionStrength = 16.0 self.reflectionStrength = 16.0
self.reflectionVisibility = 1.0 self.reflectionVisibility = 1.0
self.blur = 2.0 self.blur = 2.0
self.glowBlur = 1.0
self.glowTimer = 0.0
self.glowDown = false
self.drawBackground = function() end
self.drawForground = function() end
options = options or {}
for k, v in pairs(options) do self[k] = v end
self:refreshScreenSize() self:refreshScreenSize()
end end
function light_world:update(l,t,w,h) function light_world:drawBlur(blendmode, blur, canvas, canvas2, l, t, w, h)
l,t,w,h = self.clampScreen(l,t,w,h) if blur <= 0 then
self:updateShadows(l,t,w,h) return
self:updateShine(l,t,w,h) end
self:updatePixelShadows(l,t,w,h)
self:updateGlow(l,t,w,h) love.graphics.setColor(255, 255, 255)
self:updateRefraction(l,t,w,h) self.blurv:send("steps", blur)
self:updateRelfection(l,t,w,h) self.blurh:send("steps", blur)
love.graphics.setBlendMode(blendmode)
canvas2:clear()
love.graphics.setCanvas(canvas2)
love.graphics.setShader(self.blurv)
love.graphics.draw(canvas, l, t)
love.graphics.setCanvas(canvas)
love.graphics.setShader(self.blurh)
love.graphics.draw(canvas2, l, t)
end end
function light_world:updateShadows(l,t,w,h) function light_world:updateShadows(l,t,w,h)
if not self.isShadows and not self.isLight then local last_buffer = love.graphics.getCanvas()
return
end
self.last_buffer = love.graphics.getCanvas()
for i = 1, #self.lights do for i = 1, #self.lights do
self.lights[i]:updateShadow(l,t,w,h) self.lights[i]:updateShadow(l,t,w,h, self.body)
end end
-- update shadow -- update shadow
love.graphics.setCanvas(self.shadow) love.graphics.setCanvas(self.shadow)
love.graphics.setStencil()
love.graphics.setColor(unpack(self.ambient)) love.graphics.setColor(unpack(self.ambient))
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.rectangle("fill", l, t, w, h) love.graphics.rectangle("fill", l, t, w, h)
love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive")
for i = 1, #self.lights do for i = 1, #self.lights do
self.lights[i]:drawShadow(l,t,w,h) self.lights[i]:drawShadow(l,t,w,h)
end end
if self.blur then light_world:drawBlur("alpha", self.blur, self.shadow, self.shadow2, l, t, w, h)
love.graphics.setColor(255, 255, 255) love.graphics.setCanvas(last_buffer)
self.blurv:send("steps", self.blur)
self.blurh:send("steps", self.blur)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(self.shadow2)
love.graphics.setShader(self.blurv)
love.graphics.draw(self.shadow, l, t)
love.graphics.setCanvas(self.shadow)
love.graphics.setShader(self.blurh)
love.graphics.draw(self.shadow2, l, t)
end
love.graphics.setCanvas(self.last_buffer)
end end
function light_world:updateShine(l,t,w,h) function light_world:updateShine(l,t,w,h)
self.last_buffer = love.graphics.getCanvas() local last_buffer = love.graphics.getCanvas()
-- update shine -- update shine
love.graphics.setCanvas(self.shine) love.graphics.setCanvas(self.shine)
love.graphics.setColor(unpack(self.ambient)) love.graphics.setColor(unpack(self.ambient))
@ -121,28 +112,12 @@ function light_world:updateShine(l,t,w,h)
self.lights[i]:drawShine(l,t,w,h) self.lights[i]:drawShine(l,t,w,h)
end end
if self.blur and false then --light_world:drawBlur("additive", self.blur, self.shine, self.shine2, l, t, w, h)
love.graphics.setColor(255, 255, 255) love.graphics.setCanvas(last_buffer)
self.blurv:send("steps", self.blur)
self.blurh:send("steps", self.blur)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(self.shine2)
love.graphics.setShader(self.blurv)
love.graphics.draw(self.shine, l, t)
love.graphics.setCanvas(self.shine)
love.graphics.setShader(self.blurh)
love.graphics.draw(self.shine2, l, t)
end
love.graphics.setCanvas(self.last_buffer)
end end
function light_world:updatePixelShadows(l,t,w,h) function light_world:updatePixelShadows(l,t,w,h)
if not self.isPixelShadows then local last_buffer = love.graphics.getCanvas()
return
end
self.last_buffer = love.graphics.getCanvas()
-- update pixel shadow -- update pixel shadow
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
@ -150,19 +125,20 @@ function light_world:updatePixelShadows(l,t,w,h)
self.normalMap:clear() self.normalMap:clear()
love.graphics.setShader() love.graphics.setShader()
love.graphics.setCanvas(self.normalMap) love.graphics.setCanvas(self.normalMap)
for i = 1, #self.body do for i = 1, #self.body do
self.body[i]:drawPixelShadow(l,t,w,h) self.body[i]:drawPixelShadow(l,t,w,h)
end end
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
self.pixelShadow2:clear() self.pixelShadow2:clear()
love.graphics.setCanvas(self.pixelShadow2) love.graphics.setCanvas(self.pixelShadow2)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.setShader(self.shader2) love.graphics.setShader(self.shader2)
for i = 1, #self.lights do for i = 1, #self.lights do
self.lights[i]:drawPixelShadow(l,t,w,h) self.lights[i]:drawPixelShadow(l,t,w,h, self.normalMap)
end end
love.graphics.setShader() love.graphics.setShader()
@ -175,15 +151,11 @@ function light_world:updatePixelShadows(l,t,w,h)
love.graphics.rectangle("fill", l,t,w,h) love.graphics.rectangle("fill", l,t,w,h)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(self.last_buffer) love.graphics.setCanvas(last_buffer)
end end
function light_world:updateGlow(l,t,w,h) function light_world:updateGlow(l,t,w,h)
if not self.isGlow then local last_buffer = love.graphics.getCanvas()
return
end
self.last_buffer = love.graphics.getCanvas()
-- create glow map -- create glow map
self.glowMap:clear(0, 0, 0) self.glowMap:clear(0, 0, 0)
love.graphics.setCanvas(self.glowMap) love.graphics.setCanvas(self.glowMap)
@ -204,30 +176,12 @@ function light_world:updateGlow(l,t,w,h)
self.body[i]:drawGlow(l,t,w,h) self.body[i]:drawGlow(l,t,w,h)
end end
love.graphics.setColor(255, 255, 255) light_world:drawBlur("alpha", self.glowBlur, self.glowMap, self.glowMap2, l, t, w, h)
if self.glowBlur == 0.0 then love.graphics.setCanvas(last_buffer)
self.blurv:send("steps", self.glowBlur)
self.blurh:send("steps", self.glowBlur)
love.graphics.setBlendMode("additive")
self.glowMap2:clear()
love.graphics.setCanvas(self.glowMap2)
love.graphics.setShader(self.blurv)
love.graphics.draw(self.glowMap, l, t)
love.graphics.setCanvas(self.glowMap)
love.graphics.setShader(self.blurh)
love.graphics.draw(self.glowMap2, l, t)
love.graphics.setBlendMode("alpha")
end
love.graphics.setCanvas(self.last_buffer)
end end
function light_world:updateRefraction(l,t,w,h) function light_world:updateRefraction(l,t,w,h)
if not self.isRefraction then local last_buffer = love.graphics.getCanvas()
return
end
self.last_buffer = love.graphics.getCanvas()
-- create refraction map -- create refraction map
self.refractionMap:clear() self.refractionMap:clear()
@ -236,24 +190,20 @@ function light_world:updateRefraction(l,t,w,h)
self.body[i]:drawRefraction(l,t,w,h) self.body[i]:drawRefraction(l,t,w,h)
end end
if self.last_buffer then if last_buffer then
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(self.refractionMap2) love.graphics.setCanvas(self.refractionMap2)
love.graphics.draw(self.last_buffer, l, t) love.graphics.draw(last_buffer, l, t)
love.graphics.setCanvas(self.last_buffer) love.graphics.setCanvas(last_buffer)
love.graphics.setShader() love.graphics.setShader()
end end
love.graphics.setCanvas(self.last_buffer) love.graphics.setCanvas(last_buffer)
end end
function light_world:updateRelfection(l,t,w,h) function light_world:updateRelfection(l,t,w,h)
if not self.isReflection then local last_buffer = love.graphics.getCanvas()
return
end
self.last_buffer = love.graphics.getCanvas()
-- create reflection map -- create reflection map
self.reflectionMap:clear(0, 0, 0) self.reflectionMap:clear(0, 0, 0)
love.graphics.setCanvas(self.reflectionMap) love.graphics.setCanvas(self.reflectionMap)
@ -261,18 +211,19 @@ function light_world:updateRelfection(l,t,w,h)
self.body[i]:drawReflection(l,t,w,h) self.body[i]:drawReflection(l,t,w,h)
end end
if self.last_buffer then if last_buffer then
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(self.reflectionMap2) love.graphics.setCanvas(self.reflectionMap2)
love.graphics.draw(self.last_buffer, l, t) love.graphics.draw(last_buffer, l, t)
love.graphics.setShader() love.graphics.setShader()
end end
love.graphics.setCanvas(self.last_buffer) love.graphics.setCanvas(last_buffer)
end end
function light_world:refreshScreenSize() function light_world:refreshScreenSize()
self.render_buffer = love.graphics.newCanvas()
self.shadow = love.graphics.newCanvas() self.shadow = love.graphics.newCanvas()
self.shadow2 = love.graphics.newCanvas() self.shadow2 = love.graphics.newCanvas()
self.pixelShadow = love.graphics.newCanvas() self.pixelShadow = love.graphics.newCanvas()
@ -286,20 +237,45 @@ function light_world:refreshScreenSize()
self.refractionMap2 = love.graphics.newCanvas() self.refractionMap2 = love.graphics.newCanvas()
self.reflectionMap = love.graphics.newCanvas() self.reflectionMap = love.graphics.newCanvas()
self.reflectionMap2 = love.graphics.newCanvas() self.reflectionMap2 = love.graphics.newCanvas()
self.blurv:send("screen", {love.window.getWidth(), love.window.getHeight()})
self.blurh:send("screen", {love.window.getWidth(), love.window.getHeight()})
self.refractionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
self.reflectionShader:send("screen", {love.window.getWidth(), love.window.getHeight()})
for i = 1, #self.lights do
self.lights[i]:refresh()
end
end end
function light_world.clampScreen(l,t,w,h) function light_world:draw(l,t,w,h,s)
return (l or 0), (t or 0), (w or love.graphics.getWidth()), (h or love.graphics.getHeight()) l,t,w,h,s = (l or 0), (t or 0), (w or love.graphics.getWidth()), (h or love.graphics.getHeight()), s or 1
local last_buffer = love.graphics.getCanvas()
love.graphics.setCanvas(self.render_buffer)
self.drawBackground(l,t,w,h,s)
self:drawShadow(l,t,w,h,scale)
self.drawForground(l,t,w,h,s)
self:drawShine(l,t,w,h,scale)
self:drawPixelShadow(l,t,w,h,scale)
self:drawGlow(l,t,w,h,scale)
self:drawRefraction(l,t,w,h,scale)
self:drawReflection(l,t,w,h,scale)
love.graphics.setBackgroundColor(0, 0, 0)
love.graphics.setBlendMode("alpha")
love.graphics.setCanvas(last_buffer)
love.graphics.setShader()
love.graphics.setColor(255, 255, 255)
love.graphics.draw(self.render_buffer)
end end
-- draw shadow -- draw shadow
function light_world:drawShadow(l,t,w,h) function light_world:drawShadow(l,t,w,h,s)
if not self.isShadows and not self.isLight then if not self.isShadows and not self.isLight then
return return
end end
self:updateShadows(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
@ -308,13 +284,11 @@ function light_world:drawShadow(l,t,w,h)
end end
-- draw shine -- draw shine
function light_world:drawShine(l,t,w,h) function light_world:drawShine(l,t,w,h,s)
if not self.isShadows then if not self.isShadows then
return return
end end
self:updateShine(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
@ -323,13 +297,11 @@ function light_world:drawShine(l,t,w,h)
end end
-- draw pixel shadow -- draw pixel shadow
function light_world:drawPixelShadow(l,t,w,h) function light_world:drawPixelShadow(l,t,w,h,s)
if not self.isPixelShadows then if not self.isShadows then
return return
end end
self:updatePixelShadows(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("multiplicative") love.graphics.setBlendMode("multiplicative")
love.graphics.setShader() love.graphics.setShader()
@ -338,22 +310,18 @@ function light_world:drawPixelShadow(l,t,w,h)
end end
-- draw material -- draw material
function light_world:drawMaterial(l,t,w,h) function light_world:drawMaterial(l,t,w,h,s)
l,t,w,h = self.clampScreen(l,t,w,h)
for i = 1, #self.body do for i = 1, #self.body do
self.body[i]:drawMaterial(l,t,w,h) self.body[i]:drawMaterial(l,t,w,h)
end end
end end
-- draw glow -- draw glow
function light_world:drawGlow(l,t,w,h) function light_world:drawGlow(l,t,w,h,s)
if not self.isGlow then if not self.isShadows then
return return
end end
self:updateGlow(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.setShader() love.graphics.setShader()
@ -361,13 +329,11 @@ function light_world:drawGlow(l,t,w,h)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
end end
-- draw refraction -- draw refraction
function light_world:drawRefraction(l,t,w,h) function light_world:drawRefraction(l,t,w,h,s)
if not self.isRefraction then if not self.isRefraction then
return return
end end
self:updateRefraction(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
self.refractionShader:send("backBuffer", self.refractionMap2) self.refractionShader:send("backBuffer", self.refractionMap2)
self.refractionShader:send("refractionStrength", self.refractionStrength) self.refractionShader:send("refractionStrength", self.refractionStrength)
love.graphics.setShader(self.refractionShader) love.graphics.setShader(self.refractionShader)
@ -376,13 +342,11 @@ function light_world:drawRefraction(l,t,w,h)
end end
-- draw reflection -- draw reflection
function light_world:drawReflection(l,t,w,h) function light_world:drawReflection(l,t,w,h,s)
if not self.isReflection then if not self.isReflection then
return return
end end
self:updateRelfection(l,t,w,h)
l,t,w,h = self.clampScreen(l,t,w,h)
self.reflectionShader:send("backBuffer", self.reflectionMap2) self.reflectionShader:send("backBuffer", self.reflectionMap2)
self.reflectionShader:send("reflectionStrength", self.reflectionStrength) self.reflectionShader:send("reflectionStrength", self.reflectionStrength)
self.reflectionShader:send("reflectionVisibility", self.reflectionVisibility) self.reflectionShader:send("reflectionVisibility", self.reflectionVisibility)
@ -393,7 +357,7 @@ end
-- new light -- new light
function light_world:newLight(x, y, red, green, blue, range) function light_world:newLight(x, y, red, green, blue, range)
self.lights[#self.lights + 1] = Light(self, x, y, red, green, blue, range) self.lights[#self.lights + 1] = Light(x, y, red, green, blue, range)
self.isLight = true self.isLight = true
return self.lights[#self.lights] return self.lights[#self.lights]
end end
@ -408,12 +372,18 @@ end
function light_world:clearBodys() function light_world:clearBodys()
self.body = {} self.body = {}
self.isShadows = false self.isShadows = false
self.isPixelShadows = false
self.isGlow = false
self.isRefraction = false self.isRefraction = false
self.isReflection = false self.isReflection = false
end end
function light_world:setBackgroundMethod(fn)
self.drawBackground = fn or function() end
end
function light_world:setForegroundMethod(fn)
self.drawForground = fn or function() end
end
-- set ambient color -- set ambient color
function light_world:setAmbientColor(red, green, blue) function light_world:setAmbientColor(red, green, blue)
self.ambient = {red, green, blue} self.ambient = {red, green, blue}
@ -449,19 +419,6 @@ function light_world:setShadowBlur(blur)
self.blur = blur self.blur = blur
end end
-- set buffer
function light_world:setBuffer(buffer)
if buffer == "render" then
love.graphics.setCanvas(self.last_buffer)
else
self.last_buffer = love.graphics.getCanvas()
end
if buffer == "glow" then
love.graphics.setCanvas(self.glowMap)
end
end
-- set glow blur -- set glow blur
function light_world:setGlowStrength(strength) function light_world:setGlowStrength(strength)
self.glowBlur = strength self.glowBlur = strength
@ -484,50 +441,58 @@ end
-- new rectangle -- new rectangle
function light_world:newRectangle(x, y, w, h) function light_world:newRectangle(x, y, w, h)
self.isShadows = true
return self:newBody("rectangle", x, y, width, height) return self:newBody("rectangle", x, y, width, height)
end end
-- new circle -- new circle
function light_world:newCircle(x, y, r) function light_world:newCircle(x, y, r)
return self:newBody("circle", x, y, radius) self.isShadows = true
return self:newBody("circle", x, y, r)
end end
-- new polygon -- new polygon
function light_world:newPolygon(...) function light_world:newPolygon(...)
self.isShadows = true
return self:newBody("polygon", ...) return self:newBody("polygon", ...)
end end
-- new image -- new image
function light_world:newImage(img, x, y, width, height, ox, oy) function light_world:newImage(img, x, y, width, height, ox, oy)
self.isShadows = true
return self:newBody("image", img, x, y, width, height, ox, oy) return self:newBody("image", img, x, y, width, height, ox, oy)
end end
-- new refraction -- new refraction
function light_world:newRefraction(normal, x, y, width, height) function light_world:newRefraction(normal, x, y, width, height)
self.isRefraction = true
return self:newBody("refraction", normal, x, y, width, height) return self:newBody("refraction", normal, x, y, width, height)
end end
-- new refraction from height map -- new refraction from height map
function light_world:newRefractionHeightMap(heightMap, x, y, strength) function light_world:newRefractionHeightMap(heightMap, x, y, strength)
local normal = height_map_conv.toNormalMap(heightMap, strength) local normal = height_map_conv.toNormalMap(heightMap, strength)
self.isRefraction = true
return self.newRefraction(p, normal, x, y) return self.newRefraction(p, normal, x, y)
end end
-- new reflection -- new reflection
function light_world:newReflection(normal, x, y, width, height) function light_world:newReflection(normal, x, y, width, height)
self.isReflection = true
return self:newBody("reflection", normal, x, y, width, height) return self:newBody("reflection", normal, x, y, width, height)
end end
-- new reflection from height map -- new reflection from height map
function light_world:newReflectionHeightMap(heightMap, x, y, strength) function light_world:newReflectionHeightMap(heightMap, x, y, strength)
local normal = height_map_conv.toNormalMap(heightMap, strength) local normal = height_map_conv.toNormalMap(heightMap, strength)
self.isReflection = true
return self.newReflection(p, normal, x, y) return self.newReflection(p, normal, x, y)
end end
-- new body -- new body
function light_world:newBody(type, ...) function light_world:newBody(type, ...)
local id = #self.body + 1 local id = #self.body + 1
self.body[id] = Body(self, id, type, ...) self.body[id] = Body(id, type, ...)
return self.body[#self.body] return self.body[#self.body]
end end

View File

@ -58,6 +58,10 @@ function exf.update(dt)
end end
function exf.draw() function exf.draw()
lightWorld:draw(0, 0, love.window.getWidth(), love.window.getHeight(), 1)
end
function exf.drawBackground()
love.graphics.setBackgroundColor(0, 0, 0) love.graphics.setBackgroundColor(0, 0, 0)
love.graphics.setColor(48, 156, 225) love.graphics.setColor(48, 156, 225)
@ -71,10 +75,9 @@ function exf.draw()
love.graphics.print("Browse and click on the example you \nwant to run. To return the the example \nselection screen, press escape.", 500, 80) love.graphics.print("Browse and click on the example you \nwant to run. To return the the example \nselection screen, press escape.", 500, 80)
exf.list:draw() exf.list:draw()
end
lightWorld:update() function exf.drawForground()
lightWorld:drawShadow()
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.draw(exf.bigball, 800 - 128, 600 - 128, love.timer.getTime(), 1, 1, exf.bigball:getWidth() * 0.5, exf.bigball:getHeight() * 0.5) love.graphics.draw(exf.bigball, 800 - 128, 600 - 128, love.timer.getTime(), 1, 1, exf.bigball:getWidth() * 0.5, exf.bigball:getHeight() * 0.5)
end end
@ -179,7 +182,10 @@ function exf.resume()
love.window.setTitle("LOVE Example Browser") love.window.setTitle("LOVE Example Browser")
-- create light world -- create light world
lightWorld = LightWorld() lightWorld = LightWorld({
drawBackground = exf.drawBackground,
drawForground = exf.drawForground
})
lightWorld:setAmbientColor(127, 127, 127) lightWorld:setAmbientColor(127, 127, 127)
-- create light -- create light
@ -187,7 +193,7 @@ function exf.resume()
lightMouse:setSmooth(2) lightMouse:setSmooth(2)
-- create shadow bodys -- create shadow bodys
circleTest = lightWorld:newCircle(800 - 128, 600 - 128, 46) circleTest = lightWorld:newCircle(800 - 128, 600 - 128, exf.bigball:getWidth()*0.5)
end end
function inside(mx, my, x, y, w, h) function inside(mx, my, x, y, w, h)