diff --git a/gfx/tile_normal.png b/gfx/tile_normal.png index adc128e..7558502 100644 Binary files a/gfx/tile_normal.png and b/gfx/tile_normal.png differ diff --git a/light.lua b/light.lua index f16d440..55ab919 100644 --- a/light.lua +++ b/light.lua @@ -3,6 +3,7 @@ LOVE_LIGHT_CIRCLE = nil LOVE_LIGHT_POLY = nil LOVE_LIGHT_IMAGE = 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") @@ -46,14 +47,14 @@ function love.light.newWorld() o.changed = true end - if o.changed then - love.graphics.setCanvas(o.shadow) - o.shadow:clear(unpack(o.ambient)) - love.graphics.setBlendMode("additive") - else + --if o.changed then + --love.graphics.setCanvas(o.shadow) + --o.shadow:clear() + --love.graphics.setBlendMode("additive") + --else love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("alpha") - end + --end local lightsOnScreen = 0 LOVE_LIGHT_CIRCLE = o.circle @@ -68,21 +69,54 @@ function love.light.newWorld() 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("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("glow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength}) + o.shader:send("lightSmooth", o.lights[i].smooth) + o.shader:send("lightGlow", {1.0 - o.lights[i].glowSize, o.lights[i].glowStrength}) - if o.changed then - love.graphics.setCanvas(o.shadow) - else + --if o.changed then + --love.graphics.setCanvas(o.shadow) + --else love.graphics.setCanvas(o.lights[i].shadow) love.graphics.clear() - end + --end + + -- calculate shadows + LOVE_LIGHT_SHADOW_GEOMETRY = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_POLY, LOVE_LIGHT_CIRCLE) -- draw shadow love.graphics.setInvertedStencil(shadowStencil) 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 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 love.graphics.setCanvas(o.lights[i].shine) o.lights[i].shine:clear(255, 255, 255) @@ -103,7 +137,7 @@ function love.light.newWorld() -- update shadow love.graphics.setShader() - if not o.changed then + --if not o.changed then love.graphics.setCanvas(o.shadow) love.graphics.setStencil() love.graphics.setColor(unpack(o.ambient)) @@ -117,7 +151,7 @@ function love.light.newWorld() end end o.isShadowBlur = false - end + --end -- update 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.oy = o.height / 2 o.shine = true + o.red = 255 + o.green = 255 + o.blue = 255 + o.glassAlpha = 1.0 o.type = "rectangle" p.changed = true o.data = { @@ -546,6 +584,18 @@ function love.light.newRectangle(p, x, y, width, height) o.shine = b p.changed = true 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 o.getX = function() return o.x @@ -583,6 +633,10 @@ function love.light.newCircle(p, x, y, radius) o.y = y or 0 o.radius = radius or 200 o.shine = true + o.red = 255 + o.green = 255 + o.blue = 255 + o.glassAlpha = 1.0 o.type = "circle" p.changed = true -- set position @@ -624,6 +678,18 @@ function love.light.newCircle(p, x, y, radius) o.shine = b p.changed = true 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 o.getX = function() return o.x @@ -650,6 +716,10 @@ function love.light.newPolygon(p, ...) p.poly[#p.poly + 1] = o o.id = #p.poly o.shine = true + o.red = 255 + o.green = 255 + o.blue = 255 + o.glassAlpha = 1.0 o.type = "polygon" p.changed = true if ... then @@ -672,6 +742,18 @@ function love.light.newPolygon(p, ...) o.shine = b p.changed = true 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 o.getPoints = function() 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.imgHeight = img:getHeight() o.shine = true + o.red = 255 + o.green = 255 + o.blue = 255 + o.glassAlpha = 1.0 o.type = "image" p.changed = true o.data = { @@ -785,6 +871,18 @@ function love.light.newImage(p, img, x, y, width, height, ox, oy) o.shine = b p.changed = true 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 o.setImage = function(img) o.img = img @@ -907,7 +1005,7 @@ function calculateShadows(lightsource, geometry, circle, image) for i, v in pairs(geometry) do curPolygon = v.data - if not v.castsNoShadow then + if not v.castsNoShadow then local edgeFacingTo = {} for j=1,#curPolygon,2 do local indexOfNextVertex = (j+2) % #curPolygon @@ -951,6 +1049,10 @@ function calculateShadows(lightsource, geometry, circle, image) and curShadowGeometry[7] and curShadowGeometry[8] then + curShadowGeometry.alpha = v.glassAlpha + curShadowGeometry.red = v.red + curShadowGeometry.green = v.green + curShadowGeometry.blue = v.blue shadowGeometry[#shadowGeometry + 1] = curShadowGeometry end end @@ -973,6 +1075,10 @@ function calculateShadows(lightsource, geometry, circle, image) curShadowGeometry[6] = y3 - (lightsource.y - y3) * shadowLength curShadowGeometry[7] = x2 - (lightsource.x - x2) * 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 end @@ -980,12 +1086,15 @@ function calculateShadows(lightsource, geometry, circle, image) end shadowStencil = function() - local shadowGeometry = calculateShadows(LOVE_LIGHT_CURRENT, LOVE_LIGHT_POLY, LOVE_LIGHT_CIRCLE) - for i = 1,#shadowGeometry do - love.graphics.polygon("fill", unpack(shadowGeometry[i])) + for i = 1,#LOVE_LIGHT_SHADOW_GEOMETRY do + if LOVE_LIGHT_SHADOW_GEOMETRY[i].alpha == 1.0 then + love.graphics.polygon("fill", unpack(LOVE_LIGHT_SHADOW_GEOMETRY[i])) + end end for i = 1, #LOVE_LIGHT_POLY do - love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data)) + if LOVE_LIGHT_POLY[i].glassAlpha == 1.0 then + love.graphics.polygon("fill", unpack(LOVE_LIGHT_POLY[i].data)) + end end 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) @@ -997,14 +1106,14 @@ end polyStencil = function() 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) - end + --end end 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)) - end + --end end for i = 1, #LOVE_LIGHT_IMAGE do if LOVE_LIGHT_IMAGE[i].shine then diff --git a/main.lua b/main.lua index 81894e7..767c4b7 100644 --- a/main.lua +++ b/main.lua @@ -63,11 +63,11 @@ function love.load() tile_glow = love.graphics.newImage "gfx/tile_glow.png" -- light world - lightRange = 300 + lightRange = 400 lightSmooth = 1.0 lightWorld = love.light.newWorld() 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.setSmooth(lightSmooth) @@ -190,7 +190,8 @@ function love.draw() end 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 love.graphics.polygon("fill", phyLight[i].getPoints()) elseif phyLight[i].getType() == "circle" then @@ -207,7 +208,8 @@ function love.draw() if phyLight[i].getType() == "image" then if not normalOn then --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) elseif phyLight[i].normal then love.graphics.setColor(255, 255, 255) @@ -437,6 +439,7 @@ function love.keypressed(k, u) phyCnt = phyCnt + 1 phyLight[phyCnt] = lightWorld.newImage(blopp, mx, my, 42, 16, 21, 20) 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]) @@ -452,5 +455,40 @@ function love.keypressed(k, u) phyShape[phyCnt] = love.physics.newRectangleShape(0, 0, 64, 64) phyFixture[phyCnt] = love.physics.newFixture(phyBody[phyCnt], phyShape[phyCnt]) 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 \ No newline at end of file diff --git a/shader/poly_shadow.glsl b/shader/poly_shadow.glsl index 51ed71d..4d53e7b 100644 --- a/shader/poly_shadow.glsl +++ b/shader/poly_shadow.glsl @@ -1,7 +1,7 @@ extern vec3 lightPositionRange; extern vec3 lightColor; -extern float smooth; -extern vec2 glow; +extern float lightSmooth; +extern vec2 lightGlow; vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_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; if (distance <= lightPositionRange.z) { - if (glow.x < 1.0 && glow.y > 0.0) { - pixel.rgb = clamp(lightColor * pow(att, smooth) + pow(smoothstep(glow.x, 1.0, att), smooth) * glow.y, 0.0, 1.0); + if (lightGlow.x < 1.0 && lightGlow.y > 0.0) { + pixel.rgb = clamp(lightColor * pow(att, lightSmooth) + pow(smoothstep(lightGlow.x, 1.0, att), lightSmooth) * lightGlow.y, 0.0, 1.0); } else { - pixel.rgb = lightColor * pow(att, smooth); + pixel.rgb = lightColor * pow(att, lightSmooth); } } else { pixel.rgb = vec3(0, 0, 0);