From 9dd4e5311937a9d97f71800acc3b76584e965871 Mon Sep 17 00:00:00 2001 From: Tim Anema Date: Sat, 27 Sep 2014 13:46:46 -0400 Subject: [PATCH] light world no longer has any more globals --- examples/complex.lua | 19 +++--- lib/body.lua | 62 +++++++---------- lib/height_map_conv.lua | 50 ++++++++++++++ lib/light.lua | 124 +++++++++++++++------------------- lib/light_world.lua | 145 +++++++++------------------------------- 5 files changed, 173 insertions(+), 227 deletions(-) create mode 100644 lib/height_map_conv.lua diff --git a/examples/complex.lua b/examples/complex.lua index 0cd8aa5..a433ee3 100644 --- a/examples/complex.lua +++ b/examples/complex.lua @@ -175,20 +175,21 @@ function love.update(dt) if offsetX ~= offsetOldX or offsetY ~= offsetOldY then offsetChanged = true for i = 2, lightWorld:getLightCount() do - lightWorld:setLightPosition(i, lightWorld:getLightX(i) + (offsetX - offsetOldX), lightWorld:getLightY(i) + (offsetY - offsetOldY)) + local light = lightWorld:getLight(i) + light:setPosition(light:getX() + (offsetX - offsetOldX), light:getY() + (offsetY - offsetOldY)) end else offsetChanged = false end - for i = 1, lightWorld:getLightCount() do - lightWorld:setLightDirection(i, lightDirection) - end + for i = 1, lightWorld:getLightCount() do + lightWorld:getLight(i):setDirection(lightDirection) + end tileX = tileX + dt * 32.0 tileY = tileY + dt * 8.0 - for i = 1, phyCnt do + for i = 1, phyCnt do if phyBody[i] and (phyBody[i]:isAwake() or offsetChanged) then if offsetChanged then phyBody[i]:setX(phyBody[i]:getX() + (offsetX - offsetOldX)) @@ -209,7 +210,7 @@ function love.update(dt) phyLight[i]:setNormalTileOffset(tileX, tileY) --end if offsetChanged then - phyLight[i]:setPosition(phyLight[i].getX() + (offsetX - offsetOldX), phyLight[i].getY() + (offsetY - offsetOldY)) + phyLight[i]:setPosition(phyLight[i]:getX() + (offsetX - offsetOldX), phyLight[i]:getY() + (offsetY - offsetOldY)) end end end @@ -703,10 +704,10 @@ function love.keypressed(k, u) else light = lightWorld:newLight(mx, my, 31, 63, 127, lightRange) end - light.setSmooth(lightSmooth) - light.setGlowStrength(0.3) + light:setSmooth(lightSmooth) + light:setGlowStrength(0.3) math.randomseed(love.timer.getTime()) - light.setAngle(math.random(1, 5) * 0.1 * math.pi) + light:setAngle(math.random(1, 5) * 0.1 * math.pi) elseif k == "c" then if colorAberration == 0.0 then colorAberration = 3.0 diff --git a/lib/body.lua b/lib/body.lua index daebbe5..01e6cb5 100644 --- a/lib/body.lua +++ b/lib/body.lua @@ -1,5 +1,6 @@ local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or "" local class = require(_PACKAGE.."/class") +local height_map_conv = require(_PACKAGE..'/height_map_conv') local body = class() @@ -11,6 +12,24 @@ function body:init(world, id, type, ...) self.material = nil self.glow = nil self.world = world + + self.reflection = false + self.reflective = false + self.refraction = false + self.refractive = false + + self.shine = true + self.red = 0 + self.green = 0 + self.blue = 0 + self.alpha = 1.0 + self.glowRed = 255 + self.glowGreen = 255 + self.glowBlue = 255 + self.glowStrength = 0.0 + self.tileX = 0 + self.tileY = 0 + if self.type == "circle" then self.x = args[1] or 0 self.y = args[2] or 0 @@ -18,10 +37,6 @@ function body:init(world, id, type, ...) self.ox = args[4] or 0 self.oy = args[5] or 0 self.shadowType = "circle" - self.reflection = false - self.reflective = false - self.refraction = false - self.refractive = false world.isShadows = true elseif self.type == "rectangle" then self.x = args[1] or 0 @@ -41,18 +56,10 @@ function body:init(world, id, type, ...) self.x - self.ox, self.y - self.oy + self.height } - self.reflection = false - self.reflective = false - self.refraction = false - self.refractive = false world.isShadows = true elseif self.type == "polygon" then self.shadowType = "polygon" self.data = args or {0, 0, 0, 0, 0, 0} - self.reflection = false - self.reflective = false - self.refraction = false - self.refractive = false world.isShadows = true elseif self.type == "image" then self.img = args[1] @@ -89,10 +96,7 @@ function body:init(world, id, type, ...) self.x - self.ox, self.y - self.oy + self.height } - self.reflection = false self.reflective = true - self.refraction = false - self.refractive = false world.isShadows = true elseif self.type == "refraction" then self.normal = args[1] @@ -119,10 +123,7 @@ function body:init(world, id, type, ...) end self.ox = self.width * 0.5 self.oy = self.height * 0.5 - self.reflection = false - self.reflective = false self.refraction = true - self.refractive = false world.isRefraction = true elseif self.type == "reflection" then self.normal = args[1] @@ -150,22 +151,8 @@ function body:init(world, id, type, ...) self.ox = self.width * 0.5 self.oy = self.height * 0.5 self.reflection = true - self.reflective = false - self.refraction = false - self.refractive = false world.isReflection = true end - self.shine = true - self.red = 0 - self.green = 0 - self.blue = 0 - self.alpha = 1.0 - self.glowRed = 255 - self.glowGreen = 255 - self.glowBlue = 255 - self.glowStrength = 0.0 - self.tileX = 0 - self.tileY = 0 end -- refresh @@ -370,7 +357,7 @@ function body:setNormalMap(normal, width, height, nx, ny) end -- set height map function body:setHeightMap(heightMap, strength) - self:setNormalMap(HeightMapToNormalMap(heightMap, strength)) + self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength)) end -- generate flat normal map function body:generateNormalMapFlat(mode) @@ -443,14 +430,16 @@ function body:generateNormalMapGradient(horizontalGradient, verticalGradient) end -- generate normal map function body:generateNormalMap(strength) - self:setNormalMap(HeightMapToNormalMap(self.img, strength)) + self:setNormalMap(height_map_conv.toNormalMap(self.img, strength)) end + -- set material function body:setMaterial(material) if material then self.material = material end end + -- set normal function body:setGlowMap(glow) self.glow = glow @@ -458,6 +447,7 @@ function body:setGlowMap(glow) self.world.isGlow = true end + -- set tile offset function body:setNormalTileOffset(tx, ty) self.tileX = tx / self.normalWidth @@ -470,10 +460,12 @@ function body:setNormalTileOffset(tx, ty) } self.world.changed = true end + -- get type function body:getType() return self.type end + -- get type function body:setShadowType(type, ...) self.shadowType = type @@ -553,7 +545,6 @@ function body:drawShadow(light) end end - function body:drawPixelShadow() if self.type == "image" and self.normalMesh then love.graphics.setColor(255, 255, 255) @@ -561,7 +552,6 @@ function body:drawPixelShadow() end end - function body:drawGlow() if self.glowStrength > 0.0 then love.graphics.setColor(self.glowRed * self.glowStrength, self.glowGreen * self.glowStrength, self.glowBlue * self.glowStrength) diff --git a/lib/height_map_conv.lua b/lib/height_map_conv.lua new file mode 100644 index 0000000..0b5eea0 --- /dev/null +++ b/lib/height_map_conv.lua @@ -0,0 +1,50 @@ +height_map = {} + +function height_map.toNormalMap(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 + +return height_map diff --git a/lib/light.lua b/lib/light.lua index 51b793b..60c8495 100644 --- a/lib/light.lua +++ b/lib/light.lua @@ -22,7 +22,6 @@ function light:init(world, x, y, r, g, b, range) self.smooth = 1.0 self.glowSize = 0.1 self.glowStrength = 0.0 - self.changed = true self.visible = true end @@ -34,7 +33,6 @@ function light:setPosition(x, y, z) if z then self.z = z end - self.changed = true end end @@ -52,7 +50,6 @@ end function light:setX(x) if x ~= self.x then self.x = x - self.changed = true end end @@ -60,7 +57,6 @@ end function light:setY(y) if y ~= self.y then self.y = y - self.changed = true end end -- set color @@ -74,7 +70,6 @@ end function light:setRange(range) if range ~= self.range then self.range = range - self.changed = true end end @@ -88,9 +83,9 @@ function light:setDirection(direction) else self.direction = direction end - self.changed = true end end + -- set angle function light:setAngle(angle) if angle ~= self.angle then @@ -101,91 +96,82 @@ function light:setAngle(angle) else self.angle = angle end - self.changed = true end end + -- set glow size function light:setSmooth(smooth) self.smooth = smooth - self.changed = true end + -- set glow size function light:setGlowSize(size) self.glowSize = size - self.changed = true end + -- set glow strength function light:setGlowStrength(strength) self.glowStrength = strength - self.changed = true -end --- get type -function light:getType() - return "light" end function light:updateShadow() - if self.changed or self.changed then - if self.x + self.range > self.world.translate_x and self.x - self.range < love.graphics.getWidth() + self.world.translate_x - and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y - then - local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range} - local light = self - self.world.direction = self.world.direction + 0.002 - self.world.shader:send("lightPosition", {self.x - self.world.translate_x, love.graphics.getHeight() - (self.y - self.world.translate_y), self.z}) - self.world.shader:send("lightRange", self.range) - self.world.shader:send("lightColor", {self.red / 255.0, self.green / 255.0, self.blue / 255.0}) - self.world.shader:send("lightSmooth", self.smooth) - self.world.shader:send("lightGlow", {1.0 - self.glowSize, self.glowStrength}) - self.world.shader:send("lightAngle", math.pi - self.angle / 2.0) - self.world.shader:send("lightDirection", self.direction) + if self.x + self.range > self.world.translate_x and self.x - self.range < love.graphics.getWidth() + self.world.translate_x + and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y + then + local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range} + local light = self + self.world.direction = self.world.direction + 0.002 + self.world.shader:send("lightPosition", {self.x - self.world.translate_x, love.graphics.getHeight() - (self.y - self.world.translate_y), self.z}) + self.world.shader:send("lightRange", self.range) + self.world.shader:send("lightColor", {self.red / 255.0, self.green / 255.0, self.blue / 255.0}) + self.world.shader:send("lightSmooth", self.smooth) + self.world.shader:send("lightGlow", {1.0 - self.glowSize, self.glowStrength}) + self.world.shader:send("lightAngle", math.pi - self.angle / 2.0) + self.world.shader:send("lightDirection", self.direction) - love.graphics.setCanvas(self.shadow) - love.graphics.clear() + love.graphics.setCanvas(self.shadow) + love.graphics.clear() - -- calculate shadows - local shadow_geometry = calculateShadows(light, self.world.body) + -- calculate shadows + local shadow_geometry = self.calculateShadows(light, self.world.body) - -- draw shadow - love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body)) - love.graphics.setBlendMode("additive") - -- FIND THIS TOOOO - love.graphics.rectangle("fill", self.world.translate_x, self.world.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) + -- draw shadow + love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body)) + love.graphics.setBlendMode("additive") + -- FIND THIS TOOOO + love.graphics.rectangle("fill", self.world.translate_x, self.world.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) - -- draw color shadows - love.graphics.setBlendMode("multiplicative") - love.graphics.setShader() - for k = 1,#shadow_geometry do - if shadow_geometry[k].alpha < 1.0 then - love.graphics.setColor( - shadow_geometry[k].red * (1.0 - shadow_geometry[k].alpha), - shadow_geometry[k].green * (1.0 - shadow_geometry[k].alpha), - shadow_geometry[k].blue * (1.0 - shadow_geometry[k].alpha) - ) - love.graphics.polygon("fill", unpack(shadow_geometry[k])) - end + -- draw color shadows + love.graphics.setBlendMode("multiplicative") + love.graphics.setShader() + for k = 1,#shadow_geometry do + if shadow_geometry[k].alpha < 1.0 then + love.graphics.setColor( + shadow_geometry[k].red * (1.0 - shadow_geometry[k].alpha), + shadow_geometry[k].green * (1.0 - shadow_geometry[k].alpha), + shadow_geometry[k].blue * (1.0 - shadow_geometry[k].alpha) + ) + love.graphics.polygon("fill", unpack(shadow_geometry[k])) end - - for k = 1, #self.world.body do - self.world.body[k]:drawShadow(self) - end - - love.graphics.setShader(self.world.shader) - - -- draw shine - love.graphics.setCanvas(self.shine) - self.shine:clear(255, 255, 255) - love.graphics.setBlendMode("alpha") - love.graphics.setStencil(stencils.poly(self.world.body)) - -- WHOA THIS MAY BE THE ISSUE HERE FIND THIS! - love.graphics.rectangle("fill", self.world.translate_x, self.world.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) - - self.visible = true - else - self.visible = false end - self.changed = self.world.changed + for k = 1, #self.world.body do + self.world.body[k]:drawShadow(self) + end + + love.graphics.setShader(self.world.shader) + + -- draw shine + love.graphics.setCanvas(self.shine) + self.shine:clear(255, 255, 255) + love.graphics.setBlendMode("alpha") + love.graphics.setStencil(stencils.poly(self.world.body)) + -- WHOA THIS MAY BE THE ISSUE HERE FIND THIS! + love.graphics.rectangle("fill", self.world.translate_x, self.world.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) + + self.visible = true + else + self.visible = false end end @@ -201,7 +187,7 @@ function light:drawShine() end end -function calculateShadows(light, body) +function light.calculateShadows(light, body) local shadowGeometry = {} local shadowLength = 100000 diff --git a/lib/light_world.lua b/lib/light_world.lua index 37e3b82..3cac68d 100644 --- a/lib/light_world.lua +++ b/lib/light_world.lua @@ -25,14 +25,13 @@ local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or "" local class = require(_PACKAGE..'/class') local Light = require(_PACKAGE..'/light') local Body = require(_PACKAGE..'/body') +local height_map_conv = require(_PACKAGE..'/height_map_conv') local light_world = class() function light_world:init() self.translate_x = 0 self.translate_y = 0 - self.translate_x_old = 0 - self.translate_y_old = 0 self.direction = 0 self.last_buffer = nil @@ -78,7 +77,6 @@ function light_world:init() self.reflectionStrength = 16.0 self.reflectionVisibility = 1.0 - self.changed = true self.blur = 2.0 self.optionShadows = true self.optionPixelShadows = true @@ -96,13 +94,6 @@ end -- update function light_world:update() self.last_buffer = love.graphics.getCanvas() - - if self.translate_x ~= self.translate_x_old or self.translate_y ~= self.translate_y_old then - self.translate_x_old = self.translate_x - self.translate_y_old = self.translate_y - self.changed = true - end - love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("alpha") self:updateShadows() @@ -114,7 +105,6 @@ function light_world:update() love.graphics.setBlendMode("alpha") love.graphics.setStencil() love.graphics.setCanvas(self.last_buffer) - self.changed = false end function light_world:updateShadows() @@ -137,10 +127,10 @@ function light_world:updateShadows() love.graphics.rectangle("fill", self.translate_x, self.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("additive") + for i = 1, #self.lights do self.lights[i]:drawShadow() end - self.isShadowBlur = false -- update shine love.graphics.setCanvas(self.shine) @@ -149,6 +139,7 @@ function light_world:updateShadows() love.graphics.rectangle("fill", self.translate_x, self.translate_y, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.setColor(255, 255, 255) love.graphics.setBlendMode("additive") + for i = 1, #self.lights do self.lights[i]:drawShine() end @@ -234,12 +225,10 @@ function light_world:updateRelfection() return end -- create reflection map - if self.changed then - self.reflectionMap:clear(0, 0, 0) - love.graphics.setCanvas(self.reflectionMap) - for i = 1, #self.body do - self.body[i]:drawReflection() - end + self.reflectionMap:clear(0, 0, 0) + love.graphics.setCanvas(self.reflectionMap) + for i = 1, #self.body do + self.body[i]:drawReflection() end end @@ -424,13 +413,11 @@ end function light_world:clearLights() self.lights = {} self.isLight = false - self.changed = true end -- clear objects function light_world:clearBodys() self.body = {} - self.changed = true self.isShadows = false self.isPixelShadows = false self.isGlow = false @@ -472,13 +459,11 @@ end -- set blur function light_world:setBlur(blur) self.blur = blur - self.changed = true end -- set blur function light_world:setShadowBlur(blur) self.blur = blur - self.changed = true end -- set buffer @@ -493,160 +478,94 @@ function light_world:setBuffer(buffer) love.graphics.setCanvas(self.glowMap) end end + -- set glow blur function light_world:setGlowStrength(strength) self.glowBlur = strength - self.changed = true end + -- set refraction blur function light_world:setRefractionStrength(strength) self.refractionStrength = strength end + -- set reflection strength function light_world:setReflectionStrength(strength) self.reflectionStrength = strength end + -- set reflection visibility function light_world:setReflectionVisibility(visibility) self.reflectionVisibility = visibility end + -- new rectangle function light_world:newRectangle(x, y, w, h) return self:newBody("rectangle", x, y, width, height) end + -- new circle function light_world:newCircle(x, y, r) return self:newBody("circle", x, y, radius) end + -- new polygon function light_world:newPolygon(...) return self:newBody("polygon", ...) end + -- new image function light_world:newImage(img, x, y, width, height, ox, oy) return self:newBody("image", img, x, y, width, height, ox, oy) end + -- new refraction function light_world:newRefraction(normal, x, y, width, height) return self:newBody("refraction", normal, x, y, width, height) end + -- new refraction from height map function light_world:newRefractionHeightMap(heightMap, x, y, strength) - local normal = HeightMapToNormalMap(heightMap, strength) + local normal = height_map_conv.toNormalMap(heightMap, strength) return self.newRefraction(p, normal, x, y) end + -- new reflection function light_world:newReflection(normal, x, y, width, height) return self:newBody("reflection", normal, x, y, width, height) end + -- new reflection from height map function light_world:newReflectionHeightMap(heightMap, x, y, strength) - local normal = HeightMapToNormalMap(heightMap, strength) + local normal = height_map_conv.toNormalMap(heightMap, strength) return self.newReflection(p, normal, x, y) end + -- new body function light_world:newBody(type, ...) local id = #self.body + 1 self.body[id] = Body(self, id, type, ...) - self.changed = true return self.body[#self.body] end --- set polygon data -function light_world:setPoints(n, ...) - self.body[n].data = {...} -end --- get polygon count + +-- get body count function light_world:getBodyCount() return #self.body end --- get polygon -function light_world:getPoints(n) - if self.body[n].data then - return unpack(self.body[n].data) - end -end --- set light position -function light_world:setLightPosition(n, x, y, z) - self.lights[n]:setPosition(x, y, z) -end --- set light x -function light_world:setLightX(n, x) - self.lights[n]:setX(x) -end --- set light y -function light_world:setLightY(n, y) - self.lights[n]:setY(y) -end --- set light angle -function light_world:setLightAngle(n, angle) - self.lights[n]:setAngle(angle) -end --- set light direction -function light_world:setLightDirection(n, direction) - self.lights[n]:setDirection(direction) + +-- get light +function light_world:getBody(n) + return self.body[n] end + -- get light count function light_world:getLightCount() return #self.lights end --- get light x position -function light_world:getLightX(n) - return self.lights[n].x -end --- get light y position -function light_world:getLightY(n) - return self.lights[n].y -end --- get type -function light_world:getType() - return "world" -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) +-- get light +function light_world:getLight(n) + return self.lights[n] end return light_world