mirror of
https://github.com/tanema/light_world.lua.git
synced 2024-12-24 20:24:19 +00:00
split up calculate shadows a bit so it is a bit more managable
This commit is contained in:
parent
9dd4e53119
commit
735d565142
33
lib/body.lua
33
lib/body.lua
@ -168,6 +168,7 @@ function body:refresh()
|
|||||||
self.data[8] = self.y - self.oy + self.height
|
self.data[8] = self.y - self.oy + self.height
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set position
|
-- set position
|
||||||
function body:setPosition(x, y)
|
function body:setPosition(x, y)
|
||||||
if x ~= self.x or y ~= self.y then
|
if x ~= self.x or y ~= self.y then
|
||||||
@ -177,6 +178,7 @@ function body:setPosition(x, y)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set x position
|
-- set x position
|
||||||
function body:setX(x)
|
function body:setX(x)
|
||||||
if x ~= self.x then
|
if x ~= self.x then
|
||||||
@ -185,6 +187,7 @@ function body:setX(x)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set y position
|
-- set y position
|
||||||
function body:setY(y)
|
function body:setY(y)
|
||||||
if y ~= self.y then
|
if y ~= self.y then
|
||||||
@ -193,30 +196,37 @@ function body:setY(y)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get x position
|
-- get x position
|
||||||
function body:getX()
|
function body:getX()
|
||||||
return self.x
|
return self.x
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get y position
|
-- get y position
|
||||||
function body:getY(y)
|
function body:getY(y)
|
||||||
return self.y
|
return self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get width
|
-- get width
|
||||||
function body:getWidth()
|
function body:getWidth()
|
||||||
return self.width
|
return self.width
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get height
|
-- get height
|
||||||
function body:getHeight()
|
function body:getHeight()
|
||||||
return self.height
|
return self.height
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get image width
|
-- get image width
|
||||||
function body:getImageWidth()
|
function body:getImageWidth()
|
||||||
return self.imgWidth
|
return self.imgWidth
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get image height
|
-- get image height
|
||||||
function body:getImageHeight()
|
function body:getImageHeight()
|
||||||
return self.imgHeight
|
return self.imgHeight
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set dimension
|
-- set dimension
|
||||||
function body:setDimension(width, height)
|
function body:setDimension(width, height)
|
||||||
self.width = width
|
self.width = width
|
||||||
@ -224,6 +234,7 @@ function body:setDimension(width, height)
|
|||||||
self:refresh()
|
self:refresh()
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set offset
|
-- set offset
|
||||||
function body:setOffset(ox, oy)
|
function body:setOffset(ox, oy)
|
||||||
if ox ~= self.ox or oy ~= self.oy then
|
if ox ~= self.ox or oy ~= self.oy then
|
||||||
@ -235,6 +246,7 @@ function body:setOffset(ox, oy)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set offset
|
-- set offset
|
||||||
function body:setImageOffset(ix, iy)
|
function body:setImageOffset(ix, iy)
|
||||||
if ix ~= self.ix or iy ~= self.iy then
|
if ix ~= self.ix or iy ~= self.iy then
|
||||||
@ -244,6 +256,7 @@ function body:setImageOffset(ix, iy)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set offset
|
-- set offset
|
||||||
function body:setNormalOffset(nx, ny)
|
function body:setNormalOffset(nx, ny)
|
||||||
if nx ~= self.nx or ny ~= self.ny then
|
if nx ~= self.nx or ny ~= self.ny then
|
||||||
@ -253,6 +266,7 @@ function body:setNormalOffset(nx, ny)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set glow color
|
-- set glow color
|
||||||
function body:setGlowColor(red, green, blue)
|
function body:setGlowColor(red, green, blue)
|
||||||
self.glowRed = red
|
self.glowRed = red
|
||||||
@ -260,15 +274,18 @@ function body:setGlowColor(red, green, blue)
|
|||||||
self.glowBlue = blue
|
self.glowBlue = blue
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set glow alpha
|
-- set glow alpha
|
||||||
function body:setGlowStrength(strength)
|
function body:setGlowStrength(strength)
|
||||||
self.glowStrength = strength
|
self.glowStrength = strength
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get radius
|
-- get radius
|
||||||
function body:getRadius()
|
function body:getRadius()
|
||||||
return self.radius
|
return self.radius
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set radius
|
-- set radius
|
||||||
function body:setRadius(radius)
|
function body:setRadius(radius)
|
||||||
if radius ~= self.radius then
|
if radius ~= self.radius then
|
||||||
@ -276,25 +293,30 @@ function body:setRadius(radius)
|
|||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set polygon data
|
-- set polygon data
|
||||||
function body:setPoints(...)
|
function body:setPoints(...)
|
||||||
self.data = {...}
|
self.data = {...}
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get polygon data
|
-- get polygon data
|
||||||
function body:getPoints()
|
function body:getPoints()
|
||||||
return unpack(self.data)
|
return unpack(self.data)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set shadow on/off
|
-- set shadow on/off
|
||||||
function body:setShadow(b)
|
function body:setShadow(b)
|
||||||
self.castsNoShadow = not b
|
self.castsNoShadow = not b
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set shine on/off
|
-- set shine on/off
|
||||||
function body:setShine(b)
|
function body:setShine(b)
|
||||||
self.shine = b
|
self.shine = b
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set glass color
|
-- set glass color
|
||||||
function body:setColor(red, green, blue)
|
function body:setColor(red, green, blue)
|
||||||
self.red = red
|
self.red = red
|
||||||
@ -302,27 +324,33 @@ function body:setColor(red, green, blue)
|
|||||||
self.blue = blue
|
self.blue = blue
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set glass alpha
|
-- set glass alpha
|
||||||
function body:setAlpha(alpha)
|
function body:setAlpha(alpha)
|
||||||
self.alpha = alpha
|
self.alpha = alpha
|
||||||
self.world.changed = true
|
self.world.changed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set reflection on/off
|
-- set reflection on/off
|
||||||
function body:setReflection(reflection)
|
function body:setReflection(reflection)
|
||||||
self.reflection = reflection
|
self.reflection = reflection
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set refraction on/off
|
-- set refraction on/off
|
||||||
function body:setRefraction(refraction)
|
function body:setRefraction(refraction)
|
||||||
self.refraction = refraction
|
self.refraction = refraction
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set reflective on other objects on/off
|
-- set reflective on other objects on/off
|
||||||
function body:setReflective(reflective)
|
function body:setReflective(reflective)
|
||||||
self.reflective = reflective
|
self.reflective = reflective
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set refractive on other objects on/off
|
-- set refractive on other objects on/off
|
||||||
function body:setRefractive(refractive)
|
function body:setRefractive(refractive)
|
||||||
self.refractive = refractive
|
self.refractive = refractive
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set image
|
-- set image
|
||||||
function body:setImage(img)
|
function body:setImage(img)
|
||||||
if img then
|
if img then
|
||||||
@ -333,6 +361,7 @@ function body:setImage(img)
|
|||||||
self.iy = self.imgHeight * 0.5
|
self.iy = self.imgHeight * 0.5
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set normal
|
-- set normal
|
||||||
function body:setNormalMap(normal, width, height, nx, ny)
|
function body:setNormalMap(normal, width, height, nx, ny)
|
||||||
if normal then
|
if normal then
|
||||||
@ -355,10 +384,12 @@ function body:setNormalMap(normal, width, height, nx, ny)
|
|||||||
self.normalMesh = nil
|
self.normalMesh = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set height map
|
-- set height map
|
||||||
function body:setHeightMap(heightMap, strength)
|
function body:setHeightMap(heightMap, strength)
|
||||||
self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength))
|
self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate flat normal map
|
-- generate flat normal map
|
||||||
function body:generateNormalMapFlat(mode)
|
function body:generateNormalMapFlat(mode)
|
||||||
local imgData = self.img:getData()
|
local imgData = self.img:getData()
|
||||||
@ -388,6 +419,7 @@ function body:generateNormalMapFlat(mode)
|
|||||||
|
|
||||||
self:setNormalMap(love.graphics.newImage(imgNormalData))
|
self:setNormalMap(love.graphics.newImage(imgNormalData))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate faded normal map
|
-- generate faded normal map
|
||||||
function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
|
function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
|
||||||
local imgData = self.img:getData()
|
local imgData = self.img:getData()
|
||||||
@ -428,6 +460,7 @@ function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
|
|||||||
|
|
||||||
self:setNormalMap(love.graphics.newImage(imgNormalData))
|
self:setNormalMap(love.graphics.newImage(imgNormalData))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate normal map
|
-- generate normal map
|
||||||
function body:generateNormalMap(strength)
|
function body:generateNormalMap(strength)
|
||||||
self:setNormalMap(height_map_conv.toNormalMap(self.img, strength))
|
self:setNormalMap(height_map_conv.toNormalMap(self.img, strength))
|
||||||
|
105
lib/light.lua
105
lib/light.lua
@ -119,7 +119,6 @@ function light:updateShadow()
|
|||||||
and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y
|
and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y
|
||||||
then
|
then
|
||||||
local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range}
|
local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range}
|
||||||
local light = self
|
|
||||||
self.world.direction = self.world.direction + 0.002
|
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("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("lightRange", self.range)
|
||||||
@ -133,7 +132,7 @@ function light:updateShadow()
|
|||||||
love.graphics.clear()
|
love.graphics.clear()
|
||||||
|
|
||||||
-- calculate shadows
|
-- calculate shadows
|
||||||
local shadow_geometry = self.calculateShadows(light, self.world.body)
|
local shadow_geometry = self:calculateShadows()
|
||||||
|
|
||||||
-- draw shadow
|
-- draw shadow
|
||||||
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body))
|
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body))
|
||||||
@ -187,24 +186,42 @@ function light:drawShine()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function light.calculateShadows(light, body)
|
local shadowLength = 100000
|
||||||
|
function light:calculateShadows()
|
||||||
local shadowGeometry = {}
|
local shadowGeometry = {}
|
||||||
local shadowLength = 100000
|
local body = self.world.body
|
||||||
|
|
||||||
for i = 1, #body do
|
for i = 1, #body do
|
||||||
|
local current
|
||||||
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then
|
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then
|
||||||
curPolygon = body[i].data
|
current = self:calculatePolyShadow(body[i])
|
||||||
if not body[i].castsNoShadow then
|
elseif body[i].shadowType == "circle" then
|
||||||
|
current = self:calculateCircleShadow(body[i])
|
||||||
|
end
|
||||||
|
if current ~= nil then
|
||||||
|
shadowGeometry[#shadowGeometry + 1] = current
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return shadowGeometry
|
||||||
|
end
|
||||||
|
|
||||||
|
function light:calculatePolyShadow(poly)
|
||||||
|
if poly.castsNoShadow then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local curPolygon = poly.data
|
||||||
local edgeFacingTo = {}
|
local edgeFacingTo = {}
|
||||||
for k = 1, #curPolygon, 2 do
|
for k = 1, #curPolygon, 2 do
|
||||||
local indexOfNextVertex = (k + 2) % #curPolygon
|
local indexOfNextVertex = (k + 2) % #curPolygon
|
||||||
local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[k + 1], curPolygon[indexOfNextVertex] - curPolygon[k]}
|
local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[k + 1], curPolygon[indexOfNextVertex] - curPolygon[k]}
|
||||||
local lightToPoint = {curPolygon[k] - light.x, curPolygon[k + 1] - light.y}
|
local selfToPoint = {curPolygon[k] - self.x, curPolygon[k + 1] - self.y}
|
||||||
|
|
||||||
normal = vector.normalize(normal)
|
normal = vector.normalize(normal)
|
||||||
lightToPoint = vector.normalize(lightToPoint)
|
selfToPoint = vector.normalize(selfToPoint)
|
||||||
|
|
||||||
local dotProduct = vector.dot(normal, lightToPoint)
|
local dotProduct = vector.dot(normal, selfToPoint)
|
||||||
if dotProduct > 0 then table.insert(edgeFacingTo, true)
|
if dotProduct > 0 then table.insert(edgeFacingTo, true)
|
||||||
else table.insert(edgeFacingTo, false) end
|
else table.insert(edgeFacingTo, false) end
|
||||||
end
|
end
|
||||||
@ -217,17 +234,17 @@ function light.calculateShadows(light, body)
|
|||||||
curShadowGeometry[1] = curPolygon[nextIndex*2-1]
|
curShadowGeometry[1] = curPolygon[nextIndex*2-1]
|
||||||
curShadowGeometry[2] = curPolygon[nextIndex*2]
|
curShadowGeometry[2] = curPolygon[nextIndex*2]
|
||||||
|
|
||||||
local lightVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y})
|
local selfVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
|
||||||
curShadowGeometry[3] = curShadowGeometry[1] + lightVecFrontBack[1] * shadowLength
|
curShadowGeometry[3] = curShadowGeometry[1] + selfVecFrontBack[1] * shadowLength
|
||||||
curShadowGeometry[4] = curShadowGeometry[2] + lightVecFrontBack[2] * shadowLength
|
curShadowGeometry[4] = curShadowGeometry[2] + selfVecFrontBack[2] * shadowLength
|
||||||
|
|
||||||
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
|
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
|
||||||
curShadowGeometry[7] = curPolygon[nextIndex*2-1]
|
curShadowGeometry[7] = curPolygon[nextIndex*2-1]
|
||||||
curShadowGeometry[8] = curPolygon[nextIndex*2]
|
curShadowGeometry[8] = curPolygon[nextIndex*2]
|
||||||
|
|
||||||
local lightVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y})
|
local selfVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
|
||||||
curShadowGeometry[5] = curShadowGeometry[7] + lightVecBackFront[1] * shadowLength
|
curShadowGeometry[5] = curShadowGeometry[7] + selfVecBackFront[1] * shadowLength
|
||||||
curShadowGeometry[6] = curShadowGeometry[8] + lightVecBackFront[2] * shadowLength
|
curShadowGeometry[6] = curShadowGeometry[8] + selfVecBackFront[2] * shadowLength
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if curShadowGeometry[1]
|
if curShadowGeometry[1]
|
||||||
@ -239,44 +256,46 @@ function light.calculateShadows(light, body)
|
|||||||
and curShadowGeometry[7]
|
and curShadowGeometry[7]
|
||||||
and curShadowGeometry[8]
|
and curShadowGeometry[8]
|
||||||
then
|
then
|
||||||
curShadowGeometry.alpha = body[i].alpha
|
curShadowGeometry.alpha = poly.alpha
|
||||||
curShadowGeometry.red = body[i].red
|
curShadowGeometry.red = poly.red
|
||||||
curShadowGeometry.green = body[i].green
|
curShadowGeometry.green = poly.green
|
||||||
curShadowGeometry.blue = body[i].blue
|
curShadowGeometry.blue = poly.blue
|
||||||
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
|
return curShadowGeometry
|
||||||
|
else
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function light:calculateCircleShadow(circle)
|
||||||
|
if circle.castsNoShadow then
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
elseif body[i].shadowType == "circle" then
|
local length = math.sqrt(math.pow(self.x - (circle.x - circle.ox), 2) + math.pow(self.y - (circle.y - circle.oy), 2))
|
||||||
if not body[i].castsNoShadow then
|
if length >= circle.radius and length <= self.range 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 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 angle = math.atan2(self.x - (circle.x - circle.ox), (circle.y - circle.oy) - self.y) + math.pi / 2
|
||||||
local x2 = ((body[i].x - body[i].ox) + math.sin(angle) * body[i].radius)
|
local x2 = ((circle.x - circle.ox) + math.sin(angle) * circle.radius)
|
||||||
local y2 = ((body[i].y - body[i].oy) - math.cos(angle) * body[i].radius)
|
local y2 = ((circle.y - circle.oy) - math.cos(angle) * circle.radius)
|
||||||
local x3 = ((body[i].x - body[i].ox) - math.sin(angle) * body[i].radius)
|
local x3 = ((circle.x - circle.ox) - math.sin(angle) * circle.radius)
|
||||||
local y3 = ((body[i].y - body[i].oy) + math.cos(angle) * body[i].radius)
|
local y3 = ((circle.y - circle.oy) + math.cos(angle) * circle.radius)
|
||||||
|
|
||||||
curShadowGeometry[1] = x2
|
curShadowGeometry[1] = x2
|
||||||
curShadowGeometry[2] = y2
|
curShadowGeometry[2] = y2
|
||||||
curShadowGeometry[3] = x3
|
curShadowGeometry[3] = x3
|
||||||
curShadowGeometry[4] = y3
|
curShadowGeometry[4] = y3
|
||||||
|
|
||||||
curShadowGeometry[5] = x3 - (light.x - x3) * shadowLength
|
curShadowGeometry[5] = x3 - (self.x - x3) * shadowLength
|
||||||
curShadowGeometry[6] = y3 - (light.y - y3) * shadowLength
|
curShadowGeometry[6] = y3 - (self.y - y3) * shadowLength
|
||||||
curShadowGeometry[7] = x2 - (light.x - x2) * shadowLength
|
curShadowGeometry[7] = x2 - (self.x - x2) * shadowLength
|
||||||
curShadowGeometry[8] = y2 - (light.y - y2) * shadowLength
|
curShadowGeometry[8] = y2 - (self.y - y2) * shadowLength
|
||||||
curShadowGeometry.alpha = body[i].alpha
|
curShadowGeometry.alpha = circle.alpha
|
||||||
curShadowGeometry.red = body[i].red
|
curShadowGeometry.red = circle.red
|
||||||
curShadowGeometry.green = body[i].green
|
curShadowGeometry.green = circle.green
|
||||||
curShadowGeometry.blue = body[i].blue
|
curShadowGeometry.blue = circle.blue
|
||||||
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
|
return curShadowGeometry
|
||||||
|
else
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return shadowGeometry
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function light:drawPixelShadow()
|
function light:drawPixelShadow()
|
||||||
|
Loading…
Reference in New Issue
Block a user