Add colored/alpha shadow

This commit is contained in:
Marcus Ihde 2014-03-09 04:22:45 +01:00
parent 827394c87b
commit 3a3512083c
4 changed files with 179 additions and 32 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1012 B

After

Width:  |  Height:  |  Size: 1012 B

151
light.lua
View File

@ -3,6 +3,7 @@ LOVE_LIGHT_CIRCLE = nil
LOVE_LIGHT_POLY = nil LOVE_LIGHT_POLY = nil
LOVE_LIGHT_IMAGE = nil LOVE_LIGHT_IMAGE = nil
LOVE_LIGHT_LAST_BUFFER = nil LOVE_LIGHT_LAST_BUFFER = nil
LOVE_LIGHT_SHADOW_GEOMETRY = nil
LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl") LOVE_LIGHT_BLURV = love.graphics.newShader("shader/blurv.glsl")
LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl") LOVE_LIGHT_BLURH = love.graphics.newShader("shader/blurh.glsl")
@ -46,14 +47,14 @@ function love.light.newWorld()
o.changed = true o.changed = true
end end
if o.changed then --if o.changed then
love.graphics.setCanvas(o.shadow) --love.graphics.setCanvas(o.shadow)
o.shadow:clear(unpack(o.ambient)) --o.shadow:clear()
love.graphics.setBlendMode("additive") --love.graphics.setBlendMode("additive")
else --else
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
love.graphics.setBlendMode("alpha") love.graphics.setBlendMode("alpha")
end --end
local lightsOnScreen = 0 local lightsOnScreen = 0
LOVE_LIGHT_CIRCLE = o.circle LOVE_LIGHT_CIRCLE = o.circle
@ -68,21 +69,54 @@ function love.light.newWorld()
LOVE_LIGHT_CURRENT = o.lights[i] LOVE_LIGHT_CURRENT = o.lights[i]
o.shader:send("lightPositionRange", {o.lights[i].x - LOVE_LIGHT_TRANSLATE_X, love.graphics.getHeight() - (o.lights[i].y - LOVE_LIGHT_TRANSLATE_Y), o.lights[i].range}) o.shader:send("lightPositionRange", {o.lights[i].x - LOVE_LIGHT_TRANSLATE_X, love.graphics.getHeight() - (o.lights[i].y - LOVE_LIGHT_TRANSLATE_Y), 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("lightColor", {o.lights[i].red / 255.0, o.lights[i].green / 255.0, o.lights[i].blue / 255.0})
o.shader:send("smooth", o.lights[i].smooth) o.shader:send("lightSmooth", o.lights[i].smooth)
o.shader:send("glow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength}) o.shader:send("lightGlow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength})
if o.changed then --if o.changed then
love.graphics.setCanvas(o.shadow) --love.graphics.setCanvas(o.shadow)
else --else
love.graphics.setCanvas(o.lights[i].shadow) love.graphics.setCanvas(o.lights[i].shadow)
love.graphics.clear() love.graphics.clear()
end --end
-- calculate shadows
LOVE_LIGHT_SHADOW_GEOMETRY = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_POLY, LOVE_LIGHT_CIRCLE)
-- draw shadow -- draw shadow
love.graphics.setInvertedStencil(shadowStencil) love.graphics.setInvertedStencil(shadowStencil)
love.graphics.setBlendMode("additive") love.graphics.setBlendMode("additive")
love.graphics.rectangle("fill", LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y, love.graphics.getWidth(), love.graphics.getHeight()) 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 i = 1,#LOVE_LIGHT_SHADOW_GEOMETRY do
if LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha < 1.0 then
love.graphics.setColor(
LOVE_LIGHT_SHADOW_GEOMETRY[i].red * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha),
LOVE_LIGHT_SHADOW_GEOMETRY[i].green * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha),
LOVE_LIGHT_SHADOW_GEOMETRY[i].blue * (1.0 - LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha)
)
love.graphics.polygon("fill", unpack(LOVE_LIGHT_SHADOW_GEOMETRY[i]))
end
end
for i = 1, #LOVE_LIGHT_CIRCLE do
if LOVE_LIGHT_CIRCLE[i].glassAlpha < 1.0 then
love.graphics.setColor(LOVE_LIGHT_CIRCLE[i].red, LOVE_LIGHT_CIRCLE[i].green, LOVE_LIGHT_CIRCLE[i].blue)
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius)
end
end
for i = 1, #LOVE_LIGHT_POLY do
if LOVE_LIGHT_POLY[i].glassAlpha < 1.0 then
love.graphics.setColor(LOVE_LIGHT_POLY[i].red, LOVE_LIGHT_POLY[i].green, LOVE_LIGHT_POLY[i].blue)
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
end
end
love.graphics.setShader(o.shader)
-- draw shine -- draw shine
love.graphics.setCanvas(o.lights[i].shine) love.graphics.setCanvas(o.lights[i].shine)
o.lights[i].shine:clear(255, 255, 255) o.lights[i].shine:clear(255, 255, 255)
@ -103,7 +137,7 @@ function love.light.newWorld()
-- update shadow -- update shadow
love.graphics.setShader() love.graphics.setShader()
if not o.changed then --if not o.changed then
love.graphics.setCanvas(o.shadow) love.graphics.setCanvas(o.shadow)
love.graphics.setStencil() love.graphics.setStencil()
love.graphics.setColor(unpack(o.ambient)) love.graphics.setColor(unpack(o.ambient))
@ -117,7 +151,7 @@ function love.light.newWorld()
end end
end end
o.isShadowBlur = false o.isShadowBlur = false
end --end
-- update shine -- update shine
love.graphics.setCanvas(o.shine) love.graphics.setCanvas(o.shine)
@ -481,6 +515,10 @@ function love.light.newRectangle(p, x, y, width, height)
o.ox = o.width / 2 o.ox = o.width / 2
o.oy = o.height / 2 o.oy = o.height / 2
o.shine = true o.shine = true
o.red = 255
o.green = 255
o.blue = 255
o.glassAlpha = 1.0
o.type = "rectangle" o.type = "rectangle"
p.changed = true p.changed = true
o.data = { o.data = {
@ -546,6 +584,18 @@ function love.light.newRectangle(p, x, y, width, height)
o.shine = b o.shine = b
p.changed = true p.changed = true
end end
-- set glass color
o.setColor = function(red, green, blue)
o.red = red
o.green = green
o.blue = blue
p.changed = true
end
-- set glass alpha
o.setAlpha = function(alpha)
o.glassAlpha = alpha
p.changed = true
end
-- get x -- get x
o.getX = function() o.getX = function()
return o.x return o.x
@ -583,6 +633,10 @@ function love.light.newCircle(p, x, y, radius)
o.y = y or 0 o.y = y or 0
o.radius = radius or 200 o.radius = radius or 200
o.shine = true o.shine = true
o.red = 255
o.green = 255
o.blue = 255
o.glassAlpha = 1.0
o.type = "circle" o.type = "circle"
p.changed = true p.changed = true
-- set position -- set position
@ -624,6 +678,18 @@ function love.light.newCircle(p, x, y, radius)
o.shine = b o.shine = b
p.changed = true p.changed = true
end end
-- set glass color
o.setColor = function(red, green, blue)
o.red = red
o.green = green
o.blue = blue
p.changed = true
end
-- set glass alpha
o.setAlpha = function(alpha)
o.glassAlpha = alpha
p.changed = true
end
-- get x -- get x
o.getX = function() o.getX = function()
return o.x return o.x
@ -650,6 +716,10 @@ function love.light.newPolygon(p, ...)
p.poly[#p.poly + 1] = o p.poly[#p.poly + 1] = o
o.id = #p.poly o.id = #p.poly
o.shine = true o.shine = true
o.red = 255
o.green = 255
o.blue = 255
o.glassAlpha = 1.0
o.type = "polygon" o.type = "polygon"
p.changed = true p.changed = true
if ... then if ... then
@ -672,6 +742,18 @@ function love.light.newPolygon(p, ...)
o.shine = b o.shine = b
p.changed = true p.changed = true
end end
-- set glass color
o.setColor = function(red, green, blue)
o.red = red
o.green = green
o.blue = blue
p.changed = true
end
-- set glass alpha
o.setAlpha = function(alpha)
o.glassAlpha = alpha
p.changed = true
end
-- get polygon data -- get polygon data
o.getPoints = function() o.getPoints = function()
return unpack(o.data) return unpack(o.data)
@ -704,6 +786,10 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy)
o.imgWidth = img:getWidth() o.imgWidth = img:getWidth()
o.imgHeight = img:getHeight() o.imgHeight = img:getHeight()
o.shine = true o.shine = true
o.red = 255
o.green = 255
o.blue = 255
o.glassAlpha = 1.0
o.type = "image" o.type = "image"
p.changed = true p.changed = true
o.data = { o.data = {
@ -785,6 +871,18 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy)
o.shine = b o.shine = b
p.changed = true p.changed = true
end end
-- set glass color
o.setColor = function(red, green, blue)
o.red = red
o.green = green
o.blue = blue
p.changed = true
end
-- set glass alpha
o.setAlpha = function(alpha)
o.glassAlpha = alpha
p.changed = true
end
-- set image -- set image
o.setImage = function(img) o.setImage = function(img)
o.img = img o.img = img
@ -951,6 +1049,10 @@ function calculateShadows(lightsource, geometry, circle, image)
and curShadowGeometry[7] and curShadowGeometry[7]
and curShadowGeometry[8] and curShadowGeometry[8]
then then
curShadowGeometry.alpha = v.glassAlpha
curShadowGeometry.red = v.red
curShadowGeometry.green = v.green
curShadowGeometry.blue = v.blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
end end
end end
@ -973,6 +1075,10 @@ function calculateShadows(lightsource, geometry, circle, image)
curShadowGeometry[6] = y3 - (lightsource.y - y3) * shadowLength curShadowGeometry[6] = y3 - (lightsource.y - y3) * shadowLength
curShadowGeometry[7] = x2 - (lightsource.x - x2) * shadowLength curShadowGeometry[7] = x2 - (lightsource.x - x2) * shadowLength
curShadowGeometry[8] = y2 - (lightsource.y - y2) * shadowLength curShadowGeometry[8] = y2 - (lightsource.y - y2) * shadowLength
curShadowGeometry.alpha = v.glassAlpha
curShadowGeometry.red = v.red
curShadowGeometry.green = v.green
curShadowGeometry.blue = v.blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
end end
@ -980,13 +1086,16 @@ function calculateShadows(lightsource, geometry, circle, image)
end end
shadowStencil = function() shadowStencil = function()
local shadowGeometry = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_POLY, LOVE_LIGHT_CIRCLE) for i = 1,#LOVE_LIGHT_SHADOW_GEOMETRY do
for i = 1,#shadowGeometry do if LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha == 1.0 then
love.graphics.polygon("fill", unpack(shadowGeometry[i])) love.graphics.polygon("fill", unpack(LOVE_LIGHT_SHADOW_GEOMETRY[i]))
end
end end
for i = 1, #LOVE_LIGHT_POLY do for i = 1, #LOVE_LIGHT_POLY do
if LOVE_LIGHT_POLY[i].glassAlpha == 1.0 then
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data)) love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
end end
end
for i = 1, #LOVE_LIGHT_CIRCLE do for i = 1, #LOVE_LIGHT_CIRCLE do
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius) love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius)
end end
@ -997,14 +1106,14 @@ end
polyStencil = function() polyStencil = function()
for i = 1, #LOVE_LIGHT_CIRCLE do for i = 1, #LOVE_LIGHT_CIRCLE do
if LOVE_LIGHT_CIRCLE[i].shine then --if LOVE_LIGHT_CIRCLE[i].shine and LOVE_LIGHT_CIRCLE[i].glassAlpha == 1.0 then
love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius) love.graphics.circle("fill", LOVE_LIGHT_CIRCLE[i].x, LOVE_LIGHT_CIRCLE[i].y, LOVE_LIGHT_CIRCLE[i].radius)
end --end
end end
for i = 1, #LOVE_LIGHT_POLY do for i = 1, #LOVE_LIGHT_POLY do
if LOVE_LIGHT_POLY[i].shine then --if LOVE_LIGHT_POLY[i].shine and LOVE_LIGHT_POLY[i].glassAlpha == 1.0 then
love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data)) love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data))
end --end
end end
for i = 1, #LOVE_LIGHT_IMAGE do for i = 1, #LOVE_LIGHT_IMAGE do
if LOVE_LIGHT_IMAGE[i].shine then if LOVE_LIGHT_IMAGE[i].shine then

View File

@ -63,11 +63,11 @@ function love.load()
tile_glow = love.graphics.newImage "gfx/tile_glow.png" tile_glow = love.graphics.newImage "gfx/tile_glow.png"
-- light world -- light world
lightRange = 300 lightRange = 400
lightSmooth = 1.0 lightSmooth = 1.0
lightWorld = love.light.newWorld() lightWorld = love.light.newWorld()
lightWorld.setAmbientColor(15, 15, 31) lightWorld.setAmbientColor(15, 15, 31)
mouseLight = lightWorld.newLight(0, 0, 255, 127, 63, lightRange) mouseLight = lightWorld.newLight(0, 0, 255, 191, 127, lightRange)
mouseLight.setGlowStrength(0.3) mouseLight.setGlowStrength(0.3)
mouseLight.setSmooth(lightSmooth) mouseLight.setSmooth(lightSmooth)
@ -190,7 +190,8 @@ function love.draw()
end end
for i = 1, phyCnt do for i = 1, phyCnt do
love.graphics.setColor(math.sin(i) * 255, math.cos(i) * 255, math.tan(i) * 255) math.randomseed(i)
love.graphics.setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
if phyLight[i].getType() == "polygon" then if phyLight[i].getType() == "polygon" then
love.graphics.polygon("fill", phyLight[i].getPoints()) love.graphics.polygon("fill", phyLight[i].getPoints())
elseif phyLight[i].getType() == "circle" then elseif phyLight[i].getType() == "circle" then
@ -207,7 +208,8 @@ function love.draw()
if phyLight[i].getType() == "image" then if phyLight[i].getType() == "image" then
if not normalOn then if not normalOn then
--love.graphics.setColor(255, 255, 255) --love.graphics.setColor(255, 255, 255)
love.graphics.setColor(127 + math.sin(i) * 127, 127 + math.cos(i) * 127, 127 + math.tan(i) * 127) 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].ox2, phyLight[i].y - phyLight[i].oy2) love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ox2, phyLight[i].y - phyLight[i].oy2)
elseif phyLight[i].normal then elseif phyLight[i].normal then
love.graphics.setColor(255, 255, 255) love.graphics.setColor(255, 255, 255)
@ -437,6 +439,7 @@ function love.keypressed(k, u)
phyCnt = phyCnt + 1 phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(blopp, mx, my, 42, 16, 21, 20) phyLight[phyCnt] = lightWorld.newImage(blopp, mx, my, 42, 16, 21, 20)
phyLight[phyCnt].generateNormalMapGradient("gradient", "gradient") phyLight[phyCnt].generateNormalMapGradient("gradient", "gradient")
phyLight[phyCnt].setAlpha(0.5)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic") phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 42, 29) phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 42, 29)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
@ -452,5 +455,40 @@ function love.keypressed(k, u)
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 64, 64) phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 64, 64)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5) phyFixture[phyCnt]:setRestitution(0.5)
elseif k == "8" then
-- add rectangle
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newPolygon()
phyLight[phyCnt].setAlpha(0.5)
phyBody[phyCnt] = love.physics.newBody(physicWorld, mx, my, "dynamic")
phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, math.random(32, 64), math.random(32, 64))
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5)
math.randomseed(phyCnt)
phyLight[phyCnt].setColor(math.random(0, 255), math.random(0, 255), math.random(0, 255))
elseif k == "9" then
-- add circle
cRadius = math.random(8, 32)
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newCircle(mx, my, cRadius)
phyLight[phyCnt].setAlpha(0.5)
math.randomseed(phyCnt)
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])
phyFixture[phyCnt]:setRestitution(0.5)
elseif k == "0" then
-- add image
phyCnt = phyCnt + 1
phyLight[phyCnt] = lightWorld.newImage(cone, mx, my, 24, 12, 12, 28)
phyLight[phyCnt].setNormalMap(cone_normal)
phyLight[phyCnt].setAlpha(0.0)
math.randomseed(phyCnt)
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.newRectangleShape(0, 0, 24, 32)
phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt])
phyFixture[phyCnt]:setRestitution(0.5)
end end
end end

View File

@ -1,7 +1,7 @@
extern vec3 lightPositionRange; extern vec3 lightPositionRange;
extern vec3 lightColor; extern vec3 lightColor;
extern float smooth; extern float lightSmooth;
extern vec2 glow; extern vec2 lightGlow;
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){
vec4 pixel = Texel(texture, texture_coords); vec4 pixel = Texel(texture, texture_coords);
@ -10,10 +10,10 @@ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){
float att = 1 - distance / lightPositionRange.z; float att = 1 - distance / lightPositionRange.z;
if (distance <= lightPositionRange.z) { if (distance <= lightPositionRange.z) {
if (glow.x < 1.0 && glow.y > 0.0) { if (lightGlow.x < 1.0 && lightGlow.y > 0.0) {
pixel.rgb = clamp(lightColor * pow(att, smooth) + pow(smoothstep(glow.x, 1.0, att), smooth) * glow.y, 0.0, 1.0); pixel.rgb = clamp(lightColor * pow(att, lightSmooth) + pow(smoothstep(lightGlow.x, 1.0, att), lightSmooth) * lightGlow.y, 0.0, 1.0);
} else { } else {
pixel.rgb = lightColor * pow(att, smooth); pixel.rgb = lightColor * pow(att, lightSmooth);
} }
} else { } else {
pixel.rgb = vec3(0, 0, 0); pixel.rgb = vec3(0, 0, 0);