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.circle = {} o.poly = {} o.img = {} 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.isGlowBlur = false 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 -- update o.update = function() LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() love.graphics.setShader(o.shader) 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") local lightsOnScreen = 0 LOVE_LIGHT_CIRCLE = o.circle LOVE_LIGHT_POLY = o.poly LOVE_LIGHT_IMAGE = o.img 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.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(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 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(polyStencil) 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", 0, 0, 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 -- 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].normal then love.graphics.setColor(255, 255, 255) 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.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 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") -- 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()) 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 love.graphics.setShader() o.isGlowBlur = false -- 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.setBlendMode("replace") love.graphics.setColor(0, 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 -- create reflection map love.graphics.setBlendMode("alpha") 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 love.graphics.setShader() love.graphics.setBlendMode("alpha") love.graphics.setStencil() love.graphics.setCanvas(LOVE_LIGHT_LAST_BUFFER) o.changed = false end -- draw shadow o.drawShadow = function() love.graphics.setColor(255, 255, 255) if o.blur then LOVE_LIGHT_LAST_BUFFER = love.graphics.getCanvas() LOVE_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 -- draw shine o.drawShine = function() 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 -- draw pixel shadow o.drawPixelShadow = function() 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 -- 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() love.graphics.setColor(255, 255, 255) if o.isGlowBlur or 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.setBlendMode("additive") love.graphics.setShader() love.graphics.draw(o.glowMap, LOVE_LIGHT_TRANSLATE_X, LOVE_LIGHT_TRANSLATE_Y) love.graphics.setBlendMode("alpha") o.isGlowBlur = true end end -- draw refraction o.drawRefraction = function() 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 -- draw reflection o.drawReflection = function() 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 -- new light o.newLight = function(x, y, red, green, blue, range) o.lights[#o.lights + 1] = love.light.newLight(o, x, y, red, green, blue, range) return o.lights[#o.lights] end -- clear lights o.clearLights = function() o.lights = {} o.changed = true end -- clear objects o.clearBodys = function() o.body = {} o.changed = true 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 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 love.light.newRectangle(o, x, y, w, h) end -- new circle o.newCircle = function(x, y, r) return love.light.newCircle(o, x, y, r) end -- new polygon o.newPolygon = function(...) return love.light.newPolygon(o, ...) end -- new image o.newImage = function(img, x, y, width, height, ox, oy) return love.light.newImage(o, img, x, y, width, height, ox, oy) end -- new refraction o.newRefraction = function(normal, x, y) return love.light.newRefraction(o, normal, x, y) end -- new refraction from height map o.newRefractionHeightMap = function(heightMap, x, y, strength) return love.light.newRefractionHeightMap(o, heightMap, x, y, strength) end -- new reflection o.newReflection = function(normal, x, y) return love.light.newReflection(o, normal, x, y) end -- new reflection from height map o.newReflectionHeightMap = function(heightMap, x, y, strength) return love.light.newReflectionHeightMap(o, heightMap, x, y, strength) end -- new body o.newBody = function(type, ...) return love.light.newBody(o, type, ...) 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) o.lights[n].setPosition(x, y) 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 -- light object function love.light.newLight(p, x, y, red, green, blue, range) local o = {} o.direction = 0 o.angle = math.pi * 2.0 o.range = 0 o.shadow = love.graphics.newCanvas() o.shine = love.graphics.newCanvas() o.x = x or 0 o.y = y or 0 o.z = 15 o.red = red or 255 o.green = green or 255 o.blue = blue or 255 o.range = range or 300 o.smooth = 1.0 o.glowSize = 0.1 o.glowStrength = 0.0 o.changed = true o.visible = true -- set position o.setPosition = function(x, y) if x ~= o.x or y ~= o.y then o.x = x o.y = y o.changed = true end end -- get x o.getX = function() return o.x end -- get y o.getY = function() return o.y end -- set x o.setX = function(x) if x ~= o.x then o.x = x o.changed = true end end -- set y o.setY = function(y) if y ~= o.y then o.y = y o.changed = true end end -- set color o.setColor = function(red, green, blue) o.red = red o.green = green o.blue = blue --p.changed = true end -- set range o.setRange = function(range) if range ~= o.range then o.range = range o.changed = true end end -- set direction o.setDirection = function(direction) if direction ~= o.direction then if direction > math.pi * 2 then o.direction = math.mod(direction, math.pi * 2) elseif direction < 0.0 then o.direction = math.pi * 2 - math.mod(math.abs(direction), math.pi * 2) else o.direction = direction end o.changed = true end end -- set angle o.setAngle = function(angle) if angle ~= o.angle then if angle > math.pi then o.angle = math.mod(angle, math.pi) elseif angle < 0.0 then o.angle = math.pi - math.mod(math.abs(angle), math.pi) else o.angle = angle end o.changed = true end end -- set glow size o.setSmooth = function(smooth) o.smooth = smooth o.changed = true end -- set glow size o.setGlowSize = function(size) o.glowSize = size o.changed = true end -- set glow strength o.setGlowStrength = function(strength) o.glowStrength = strength o.changed = true end -- get type o.getType = function() return "light" end return o end -- body object function love.light.newBody(p, type, ...) local args = {...} local o = {} p.body[#p.body + 1] = o p.changed = true o.id = #p.body o.type = type o.normal = nil o.material = nil o.glow = nil 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 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 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 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 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 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 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 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 -- refresh o.refresh = function() if o.data then o.data[1] = o.x - o.ox o.data[2] = o.y - o.oy o.data[3] = o.x - o.ox + o.width o.data[4] = o.y - o.oy o.data[5] = o.x - o.ox + o.width o.data[6] = o.y - o.oy + o.height o.data[7] = o.x - o.ox o.data[8] = o.y - o.oy + o.height end end -- set position o.setPosition = function(x, y) if x ~= o.x or y ~= o.y then o.x = x o.y = y o.refresh() p.changed = true end end -- set x position o.setX = function(x) if x ~= o.x then o.x = x o.refresh() p.changed = true end end -- set y position o.setY = function(y) if y ~= o.y then o.y = y o.refresh() p.changed = true end end -- get x position o.getX = function() return o.x end -- get y position o.getY = function(y) return o.y end -- get width o.getWidth = function() return o.width end -- get height o.getHeight = function() return o.height end -- get image width o.getImageWidth = function() return o.imgWidth end -- get image height o.getImageHeight = function() return o.imgHeight end -- set dimension o.setDimension = function(width, height) o.width = width o.height = height o.refresh() p.changed = true end -- set offset o.setOffset = function(ox, oy) if ox ~= o.ox or oy ~= o.oy then o.ox = ox o.oy = oy if o.shadowType == "rectangle" then o.refresh() end p.changed = true end end -- set offset o.setImageOffset = function(ix, iy) if ix ~= o.ix or iy ~= o.iy then o.ix = ix o.iy = iy o.refresh() p.changed = true end end -- set offset o.setNormalOffset = function(nx, ny) if nx ~= o.nx or ny ~= o.ny then o.nx = nx o.ny = ny o.refresh() p.changed = true end end -- set glow color o.setGlowColor = function(red, green, blue) o.glowRed = red o.glowGreen = green o.glowBlue = blue p.changed = true end -- set glow alpha o.setGlowStrength = function(strength) o.glowStrength = strength p.changed = true end -- get radius o.getRadius = function() return o.radius end -- set radius o.setRadius = function(radius) if radius ~= o.radius then o.radius = radius p.changed = true end end -- set polygon data o.setPoints = function(...) o.data = {...} p.changed = true end -- get polygon data o.getPoints = function() return unpack(o.data) end -- set shadow on/off o.setShadowType = function(type) o.shadowType = type p.changed = true end -- set shadow on/off o.setShadow = function(b) o.castsNoShadow = not b p.changed = true end -- set shine on/off o.setShine = function(b) o.shine = b p.changed = true end -- 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.alpha = alpha p.changed = true end -- set reflection on/off o.setReflection = function(reflection) o.reflection = reflection end -- set refraction on/off o.setRefraction = function(refraction) o.refraction = refraction end -- set reflective on other objects on/off o.setReflective = function(reflective) o.reflective = reflective end -- set refractive on other objects on/off o.setRefractive = function(refractive) o.refractive = refractive end -- set image o.setImage = function(img) if img then o.img = img o.imgWidth = o.img:getWidth() o.imgHeight = o.img:getHeight() o.ix = o.imgWidth * 0.5 o.iy = o.imgHeight * 0.5 end end -- set normal o.setNormalMap = function(normal) if normal then o.normal = normal o.normalWidth = o.normal:getWidth() o.normalHeight = o.normal:getHeight() o.nx = o.normalWidth * 0.5 o.ny = o.normalHeight * 0.5 end end -- set height map o.setHeightMap = function(heightMap, strength) o.normal = HeightMapToNormalMap(heightMap, strength) o.normalWidth = o.normal:getWidth() o.normalHeight = o.normal:getHeight() o.nx = o.normalWidth * 0.5 o.ny = o.normalHeight * 0.5 end -- generate flat normal map o.generateNormalMapFlat = function(mode) local imgData = o.img:getData() local imgNormalData = love.image.newImageData(o.imgWidth, o.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, o.imgHeight - 1 do for k = 0, o.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 o.normal = love.graphics.newImage(imgNormalData) o.normalWidth = o.normal:getWidth() o.normalHeight = o.normal:getHeight() o.nx = o.normalWidth * 0.5 o.ny = o.normalHeight * 0.5 end -- generate faded normal map o.generateNormalMapGradient = function(horizontalGradient, verticalGradient) local imgData = o.img:getData() local imgNormalData = love.image.newImageData(o.imgWidth, o.imgHeight) local dx = 255.0 / o.imgWidth local dy = 255.0 / o.imgHeight local nx local ny local nz for i = 0, o.imgWidth - 1 do for k = 0, o.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 o.normal = love.graphics.newImage(imgNormalData) o.normalWidth = o.normal:getWidth() o.normalHeight = o.normal:getHeight() o.nx = o.normalWidth * 0.5 o.ny = o.normalHeight * 0.5 end -- generate normal map o.generateNormalMap = function(strength) o.normal = HeightMapToNormalMap(o.img, strength) o.normalWidth = o.normal:getWidth() o.normalHeight = o.normal:getHeight() o.nx = o.normalWidth * 0.5 o.ny = o.normalHeight * 0.5 end -- set material o.setMaterial = function(material) if material then o.material = material end end -- set normal o.setGlowMap = function(glow) o.glow = glow o.glowStrength = 1.0 end -- set tile offset o.setNormalTileOffset = function(tx, ty) o.tileX = tx / o.normalWidth o.tileY = ty / o.normalHeight o.normalVert = { {0.0, 0.0, o.tileX, o.tileY}, {o.normalWidth, 0.0, o.tileX + 1.0, o.tileY}, {o.normalWidth, o.normalHeight, o.tileX + 1.0, o.tileY + 1.0}, {0.0, o.normalHeight, o.tileX, o.tileY + 1.0} } p.changed = true end -- get type o.getType = function() return o.type end -- get type o.setShadowType = function(type, ...) o.shadowType = type local args = {...} if o.shadowType == "circle" then o.radius = args[1] or 16 o.ox = args[2] or 0 o.oy = args[3] or 0 elseif o.shadowType == "rectangle" then o.width = args[1] or 64 o.height = args[2] or 64 o.ox = args[3] or o.width * 0.5 o.oy = args[4] or o.height * 0.5 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 } elseif o.shadowType == "polygon" then o.data = args or {0, 0, 0, 0, 0, 0} elseif o.shadowType == "image" then if o.img then o.width = o.imgWidth o.height = o.imgHeight o.shadowVert = { {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} } if not o.shadowMesh then o.shadowMesh = love.graphics.newMesh(o.shadowVert, o.img, "fan") o.shadowMesh:setVertexColors(true) end else o.width = 64 o.height = 64 end o.shadowX = args[1] or 0 o.shadowY = args[2] or 0 o.fadeStrength = args[3] or 0.0 end end return o end -- rectangle object function love.light.newRectangle(p, x, y, width, height) return p.newBody("rectangle", x, y, width, height) end -- circle object function love.light.newCircle(p, x, y, radius) return p.newBody("circle", x, y, radius) end -- poly object function love.light.newPolygon(p, ...) return p.newBody("polygon", ...) end -- image object function love.light.newImage(p, img, x, y, width, height, ox, oy) return p.newBody("image", img, x, y, width, height, ox, oy) end -- refraction object function love.light.newRefraction(p, normal, x, y, width, height) return p.newBody("refraction", normal, x, y, width, height) end -- refraction object (height map) function love.light.newRefractionHeightMap(p, heightMap, x, y, strength) local normal = HeightMapToNormalMap(heightMap, strength) return love.light.newRefraction(p, normal, x, y) end -- reflection object function love.light.newReflection(p, normal, x, y, width, height) return p.newBody("reflection", normal, x, y, width, height) end -- reflection object (height map) function love.light.newReflectionHeightMap(p, heightMap, x, y, strength) local normal = HeightMapToNormalMap(heightMap, strength) return love.light.newReflection(p, normal, x, y) end -- vector functions function normalize(v) local len = math.sqrt(math.pow(v[1], 2) + math.pow(v[2], 2)) local normalizedv = {v[1] / len, v[2] / len} return normalizedv end function dot(v1, v2) return v1[1] * v2[1] + v1[2] * v2[2] end function lengthSqr(v) return v[1] * v[1] + v[2] * v[2] end function length(v) return math.sqrt(lengthSqr(v)) end function calculateShadows(light, body) local shadowGeometry = {} local shadowLength = 10000 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 = normalize(normal) lightToPoint = normalize(lightToPoint) local dotProduct = dot(normal, lightToPoint) if dotProduct > 0 then table.insert(edgeFacingTo, true) else table.insert(edgeFacingTo, false) end end local curShadowGeometry = {} for 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 = 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 = 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 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 return shadowGeometry end shadowStencil = function() 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_BODY do if LOVE_LIGHT_BODY[i].shadowType == "circle" then love.graphics.circle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].radius) elseif LOVE_LIGHT_BODY[i].shadowType == "rectangle" then love.graphics.rectangle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].width, LOVE_LIGHT_BODY[i].height) elseif LOVE_LIGHT_BODY[i].shadowType == "polygon" then love.graphics.polygon("fill", unpack(LOVE_LIGHT_BODY[i].data)) elseif LOVE_LIGHT_BODY[i].shadowType == "image" then --love.graphics.rectangle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].width, LOVE_LIGHT_BODY[i].height) end end end polyStencil = function() for i = 1, #LOVE_LIGHT_BODY do if LOVE_LIGHT_BODY[i].shine and (LOVE_LIGHT_BODY[i].glowStrength == 0.0 or (LOVE_LIGHT_BODY[i].type == "image" and not LOVE_LIGHT_BODY[i].normal)) then if LOVE_LIGHT_BODY[i].shadowType == "circle" then love.graphics.circle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].radius) elseif LOVE_LIGHT_BODY[i].shadowType == "rectangle" then love.graphics.rectangle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].width, LOVE_LIGHT_BODY[i].height) elseif LOVE_LIGHT_BODY[i].shadowType == "polygon" then love.graphics.polygon("fill", unpack(LOVE_LIGHT_BODY[i].data)) elseif LOVE_LIGHT_BODY[i].shadowType == "image" then --love.graphics.rectangle("fill", LOVE_LIGHT_BODY[i].x - LOVE_LIGHT_BODY[i].ox, LOVE_LIGHT_BODY[i].y - LOVE_LIGHT_BODY[i].oy, LOVE_LIGHT_BODY[i].width, LOVE_LIGHT_BODY[i].height) end end end 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