diff --git a/README.md b/README.md index df549f9..9fa0ea1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ :todoing -make sure all draw calls check if the object is within range +-add body animations -optimize shadow body calculations and drawing methods # light_world.lua diff --git a/examples/short.lua b/examples/short.lua index a316015..58d5504 100644 --- a/examples/short.lua +++ b/examples/short.lua @@ -165,7 +165,6 @@ function love.draw() end) love.graphics.pop() - love.graphics.setBlendMode("alpha") love.graphics.setColor(0, 0, 0, 191) love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), 24) diff --git a/lib/body.lua b/lib/body.lua index f805fad..6c557a3 100644 --- a/lib/body.lua +++ b/lib/body.lua @@ -24,6 +24,9 @@ function body:init(id, type, ...) self.tileX = 0 self.tileY = 0 self.zheight = 1 + + self.castsNoShadow = false + self.visible = true if self.type == "circle" then self.x = args[1] or 0 @@ -218,6 +221,10 @@ function body:setGlowStrength(strength) self.glowStrength = strength end +function body:setVisible(visible) + self.visible = visible +end + -- get radius function body:getRadius() return self.radius @@ -434,6 +441,27 @@ function body:setShadowType(type, ...) end end +function body:isInLightRange(light, l, t, w, h, s) + local distance + if self.type == 'circle' then + return light.range > math.sqrt(math.pow(light.x - self.x, 2) + math.pow(light.y - self.y, 2)) + else + local cx, cy = self.x + (self.width * 0.5), self.y + (self.height * 0.5) + distance = math.sqrt(math.pow(light.x - cx, 2) + math.pow(light.y - cy, 2)) + return distance <= light.range + (self.width > self.height and self.width or self.height) + end +end + +function body:isInRange(l, t, w, h, s) + local bx, by, bw, bh + if self.type == 'circle' then + bx, by, bw, bh = (self.x + l/s) * s, (self.y + t/s) * s, self.radius/s, self.radius/s + else + bx, by, bw, bh = (self.x + l/s) * s, (self.y + t/s) * s, self.width/s, self.height/s + end + return self.visible and (bx + bw) > 0 and (bx - bw) < w/s and (by + bh) > 0 and (by - bh) < h/s +end + function body:drawNormal() if not self.refraction and not self.reflection and self.normalMesh then love.graphics.setColor(255, 255, 255) diff --git a/lib/init.lua b/lib/init.lua index cf8327a..6cb34de 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -103,21 +103,27 @@ function light_world:drawNormalShading(l,t,w,h,s) self.normalMap:clear() util.drawto(self.normalMap, l, t, s, function() for i = 1, #self.body do - self.body[i]:drawNormal() + if self.body[i]:isInRange(l,t,w,h,s) then + self.body[i]:drawNormal() + end end end) self.normal2:clear() for i = 1, #self.lights do - -- create shadow map for this light - self.shadowMap:clear() - util.drawto(self.shadowMap, l, t, s, function() - for k = 1, #self.body do - self.body[k]:drawShadow(self.lights[i]) - end - end) - -- draw scene for this light using normals and shadowmap - self.lights[i]:drawNormalShading(l,t,w,h,s, self.normalMap, self.shadowMap, self.normal2) + if self.lights[i]:inRange(l,t,w,h,s) then + -- create shadow map for this light + self.shadowMap:clear() + util.drawto(self.shadowMap, l, t, s, function() + for k = 1, #self.body do + if self.body[k]:isInLightRange(self.lights[i]) and self.body[k]:isInRange(l,t,w,h,s) then + self.body[k]:drawShadow(self.lights[i]) + end + end + end) + -- draw scene for this light using normals and shadowmap + self.lights[i]:drawNormalShading(l,t,w,h,s, self.normalMap, self.shadowMap, self.normal2) + end end -- add in ambient color @@ -135,7 +141,9 @@ end -- draw material function light_world:drawMaterial(l,t,w,h,s) for i = 1, #self.body do - self.body[i]:drawMaterial() + if self.body[i]:isInRange(l,t,w,h,s) then + self.body[i]:drawMaterial() + end end end @@ -155,7 +163,9 @@ function light_world:drawGlow(l,t,w,h,s) self.glowMap:clear(0, 0, 0) util.drawto(self.glowMap, l, t, s, function() for i = 1, #self.body do - self.body[i]:drawGlow() + if self.body[i]:isInRange(l,t,w,h,s) then + self.body[i]:drawGlow() + end end end) @@ -188,7 +198,9 @@ function light_world:drawReflection(l,t,w,h,s) self.reflectionMap:clear(0, 0, 0) util.drawto(self.reflectionMap, l, t, s, function() for i = 1, #self.body do - self.body[i]:drawReflection() + if self.body[i]:isInRange(l,t,w,h,s) then + self.body[i]:drawReflection() + end end end) diff --git a/lib/light.lua b/lib/light.lua index 25e2d6e..4e577ad 100644 --- a/lib/light.lua +++ b/lib/light.lua @@ -114,25 +114,23 @@ end function light:inRange(l,t,w,h,s) local lx, ly, rs = (self.x + l/s) * s, (self.y + t/s) * s, self.range * s - return (lx + rs) > 0 and (lx - rs) < w/s and (ly + rs) > 0 and (ly - rs) < h/s + return self.visible and (lx + rs) > 0 and (lx - rs) < w/s and (ly + rs) > 0 and (ly - rs) < h/s end function light:drawNormalShading(l,t,w,h,s, normalMap, shadowMap, canvas) - if self.visible and self:inRange(l,t,w,h,s) then - self.shadowShader:send('shadowMap', shadowMap) - self.shadowShader:send('lightColor', {self.red / 255.0, self.green / 255.0, self.blue / 255.0}) - self.shadowShader:send("lightPosition", {(self.x + l/s) * s, (h/s - (self.y + t/s)) * s, (self.z * 10) / 255.0}) - self.shadowShader:send('lightRange',{self.range * s}) - self.shadowShader:send("lightSmooth", self.smooth) - self.shadowShader:send("lightGlow", {1.0 - self.glowSize, self.glowStrength}) - self.shadowShader:send("lightAngle", math.pi - self.angle / 2.0) - self.shadowShader:send("lightDirection", self.direction) - self.shadowShader:send("invert_normal", self.normalInvert == true) - util.drawCanvasToCanvas(normalMap, canvas, { - blendmode = 'additive', - shader = self.shadowShader - }) - end + self.shadowShader:send('shadowMap', shadowMap) + self.shadowShader:send('lightColor', {self.red / 255.0, self.green / 255.0, self.blue / 255.0}) + self.shadowShader:send("lightPosition", {(self.x + l/s) * s, (h/s - (self.y + t/s)) * s, (self.z * 10) / 255.0}) + self.shadowShader:send('lightRange',{self.range * s}) + self.shadowShader:send("lightSmooth", self.smooth) + self.shadowShader:send("lightGlow", {1.0 - self.glowSize, self.glowStrength}) + self.shadowShader:send("lightAngle", math.pi - self.angle / 2.0) + self.shadowShader:send("lightDirection", self.direction) + self.shadowShader:send("invert_normal", self.normalInvert == true) + util.drawCanvasToCanvas(normalMap, canvas, { + blendmode = 'additive', + shader = self.shadowShader + }) end function light:setVisible(visible)