mirror of
https://github.com/tanema/light_world.lua.git
synced 2024-12-24 20:24:19 +00:00
refactor body and light code to minimize size of monolithic method
This commit is contained in:
parent
fd58dd6a86
commit
08e50a7b2a
115
lib/body.lua
115
lib/body.lua
@ -523,4 +523,119 @@ function body:setShadowType(type, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function body:drawShadow(light)
|
||||||
|
if self.alpha < 1.0 then
|
||||||
|
love.graphics.setBlendMode("multiplicative")
|
||||||
|
love.graphics.setColor(self.red, self.green, self.blue)
|
||||||
|
if self.shadowType == "circle" then
|
||||||
|
love.graphics.circle("fill", self.x - self.ox, self.y - self.oy, self.radius)
|
||||||
|
elseif self.shadowType == "rectangle" then
|
||||||
|
love.graphics.rectangle("fill", self.x - self.ox, self.y - self.oy, self.width, self.height)
|
||||||
|
elseif self.shadowType == "polygon" then
|
||||||
|
love.graphics.polygon("fill", unpack(self.data))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.shadowType == "image" and self.img then
|
||||||
|
love.graphics.setBlendMode("alpha")
|
||||||
|
local length = 1.0
|
||||||
|
local shadowRotation = math.atan2((self.x) - light.x, (self.y + self.oy) - light.y)
|
||||||
|
|
||||||
|
self.shadowVert = {
|
||||||
|
{math.sin(shadowRotation) * self.imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * self.imgHeight + (math.cos(shadowRotation) + 1.0) * self.shadowY, 0, 0, self.red, self.green, self.blue, self.alpha * self.fadeStrength * 255},
|
||||||
|
{self.imgWidth + math.sin(shadowRotation) * self.imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * self.imgHeight + (math.cos(shadowRotation) + 1.0) * self.shadowY, 1, 0, self.red, self.green, self.blue, self.alpha * self.fadeStrength * 255},
|
||||||
|
{self.imgWidth, self.imgHeight + (math.cos(shadowRotation) + 1.0) * self.shadowY, 1, 1, self.red, self.green, self.blue, self.alpha * 255},
|
||||||
|
{0, self.imgHeight + (math.cos(shadowRotation) + 1.0) * self.shadowY, 0, 1, self.red, self.green, self.blue, self.alpha * 255}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shadowMesh:setVertices(self.shadowVert)
|
||||||
|
love.graphics.draw(self.shadowMesh, self.x - self.ox + self.world.translate_x, self.y - self.oy + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function body:drawPixelShadow()
|
||||||
|
if self.type == "image" and self.normalMesh then
|
||||||
|
love.graphics.setColor(255, 255, 255)
|
||||||
|
love.graphics.draw(self.normalMesh, self.x - self.nx + self.world.translate_x, self.y - self.ny + self.world.translate_y)
|
||||||
|
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)
|
||||||
|
else
|
||||||
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.type == "circle" then
|
||||||
|
love.graphics.circle("fill", self.x, self.y, self.radius)
|
||||||
|
elseif self.type == "rectangle" then
|
||||||
|
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
|
||||||
|
elseif self.type == "polygon" then
|
||||||
|
love.graphics.polygon("fill", unpack(self.data))
|
||||||
|
elseif self.type == "image" and self.img then
|
||||||
|
if self.glowStrength > 0.0 and self.glow then
|
||||||
|
love.graphics.setShader(self.world.glowShader)
|
||||||
|
self.world.glowShader:send("glowImage", self.glow)
|
||||||
|
self.world.glowShader:send("glowTime", love.timer.getTime() * 0.5)
|
||||||
|
love.graphics.setColor(255, 255, 255)
|
||||||
|
else
|
||||||
|
love.graphics.setShader()
|
||||||
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
end
|
||||||
|
love.graphics.draw(self.img, self.x - self.ix + self.world.translate_x, self.y - self.iy + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function body:drawRefraction()
|
||||||
|
if self.refraction and self.normal then
|
||||||
|
love.graphics.setColor(255, 255, 255)
|
||||||
|
if self.tileX == 0.0 and self.tileY == 0.0 then
|
||||||
|
love.graphics.draw(normal, self.x - self.nx + self.world.translate_x, self.y - self.ny + self.world.translate_y)
|
||||||
|
else
|
||||||
|
self.normalMesh:setVertices(self.normalVert)
|
||||||
|
love.graphics.draw(self.normalMesh, self.x - self.nx + self.world.translate_x, self.y - self.ny + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
|
||||||
|
if not self.refractive then
|
||||||
|
if self.type == "circle" then
|
||||||
|
love.graphics.circle("fill", self.x, self.y, self.radius)
|
||||||
|
elseif self.type == "rectangle" then
|
||||||
|
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
|
||||||
|
elseif self.type == "polygon" then
|
||||||
|
love.graphics.polygon("fill", unpack(self.data))
|
||||||
|
elseif self.type == "image" and self.img then
|
||||||
|
love.graphics.draw(self.img, self.x - self.ix + self.world.translate_x, self.y - self.iy + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function body:drawReflection()
|
||||||
|
if self.reflection and self.normal then
|
||||||
|
love.graphics.setColor(255, 0, 0)
|
||||||
|
self.normalMesh:setVertices(self.normalVert)
|
||||||
|
love.graphics.draw(self.normalMesh, self.x - self.nx + self.world.translate_x, self.y - self.ny + self.world.translate_y)
|
||||||
|
end
|
||||||
|
if self.reflective and self.img then
|
||||||
|
love.graphics.setColor(0, 255, 0)
|
||||||
|
love.graphics.draw(self.img, self.x - self.ix + self.world.translate_x, self.y - self.iy + self.world.translate_y)
|
||||||
|
elseif not self.reflection and self.img then
|
||||||
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
love.graphics.draw(self.img, self.x - self.ix + self.world.translate_x, self.y - self.iy + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function body:drawMaterial()
|
||||||
|
if self.material and self.normal then
|
||||||
|
love.graphics.setColor(255, 255, 255)
|
||||||
|
self.world.materialShader:send("material", self.material)
|
||||||
|
love.graphics.draw(self.normal, self.x - self.nx + self.world.translate_x, self.y - self.ny + self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return body
|
return body
|
||||||
|
196
lib/light.lua
196
lib/light.lua
@ -1,5 +1,7 @@
|
|||||||
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
|
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
|
||||||
local class = require(_PACKAGE.."/class")
|
local class = require(_PACKAGE.."/class")
|
||||||
|
local stencils = require(_PACKAGE..'/stencils')
|
||||||
|
local vector = require(_PACKAGE..'/vector')
|
||||||
|
|
||||||
local light = class()
|
local light = class()
|
||||||
|
|
||||||
@ -122,4 +124,198 @@ function light:getType()
|
|||||||
return "light"
|
return "light"
|
||||||
end
|
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)
|
||||||
|
|
||||||
|
love.graphics.setCanvas(self.shadow)
|
||||||
|
love.graphics.clear()
|
||||||
|
|
||||||
|
-- calculate shadows
|
||||||
|
local shadow_geometry = 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 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
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function light:drawShadow()
|
||||||
|
if self.visible then
|
||||||
|
love.graphics.draw(self.shadow, self.world.translate_x, self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function light:drawShine()
|
||||||
|
if self.visible then
|
||||||
|
love.graphics.draw(self.shine, self.world.translate_x, self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function calculateShadows(light, body)
|
||||||
|
local shadowGeometry = {}
|
||||||
|
local shadowLength = 100000
|
||||||
|
|
||||||
|
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 = vector.normalize(normal)
|
||||||
|
lightToPoint = vector.normalize(lightToPoint)
|
||||||
|
|
||||||
|
local dotProduct = vector.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 = vector.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 = vector.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
|
||||||
|
if not body[i].castsNoShadow 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
|
||||||
|
end
|
||||||
|
|
||||||
|
return shadowGeometry
|
||||||
|
end
|
||||||
|
|
||||||
|
function light:drawPixelShadow()
|
||||||
|
if self.visible then
|
||||||
|
if self.normalInvert then
|
||||||
|
self.world.normalInvertShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
|
||||||
|
self.world.normalInvertShader:send('lightColor', {self.red / 255.0, self.green / 255.0, self.blue / 255.0})
|
||||||
|
self.world.normalInvertShader:send('lightPosition',{self.x, love.graphics.getHeight() - self.y, self.z / 255.0})
|
||||||
|
self.world.normalInvertShader:send('lightRange',{self.range})
|
||||||
|
self.world.normalInvertShader:send("lightSmooth", self.smooth)
|
||||||
|
self.world.normalInvertShader:send("lightAngle", math.pi - self.angle / 2.0)
|
||||||
|
self.world.normalInvertShader:send("lightDirection", self.direction)
|
||||||
|
love.graphics.setShader(self.world.normalInvertShader)
|
||||||
|
else
|
||||||
|
self.world.normalShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
|
||||||
|
self.world.normalShader:send('lightColor', {self.red / 255.0, self.green / 255.0, self.blue / 255.0})
|
||||||
|
self.world.normalShader:send('lightPosition',{self.x, love.graphics.getHeight() - self.y, self.z / 255.0})
|
||||||
|
self.world.normalShader:send('lightRange',{self.range})
|
||||||
|
self.world.normalShader:send("lightSmooth", self.smooth)
|
||||||
|
self.world.normalShader:send("lightAngle", math.pi - self.angle / 2.0)
|
||||||
|
self.world.normalShader:send("lightDirection", self.direction)
|
||||||
|
love.graphics.setShader(self.world.normalShader)
|
||||||
|
end
|
||||||
|
love.graphics.draw(self.world.normalMap, self.world.translate_x, self.world.translate_y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return light
|
return light
|
||||||
|
@ -23,8 +23,6 @@ SOFTWARE.
|
|||||||
]]
|
]]
|
||||||
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
|
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
|
||||||
local class = require(_PACKAGE..'/class')
|
local class = require(_PACKAGE..'/class')
|
||||||
local stencils = require(_PACKAGE..'/stencils')
|
|
||||||
local vector = require(_PACKAGE..'/vector')
|
|
||||||
local Light = require(_PACKAGE..'/light')
|
local Light = require(_PACKAGE..'/light')
|
||||||
local Body = require(_PACKAGE..'/body')
|
local Body = require(_PACKAGE..'/body')
|
||||||
|
|
||||||
@ -111,97 +109,8 @@ function light_world:update()
|
|||||||
if self.optionShadows and (self.isShadows or self.isLight) then
|
if self.optionShadows and (self.isShadows or self.isLight) then
|
||||||
love.graphics.setShader(self.shader)
|
love.graphics.setShader(self.shader)
|
||||||
|
|
||||||
local lightsOnScreen = 0
|
|
||||||
for i = 1, #self.lights do
|
for i = 1, #self.lights do
|
||||||
if self.lights[i].changed or self.changed then
|
self.lights[i]:updateShadow()
|
||||||
if self.lights[i].x + self.lights[i].range > self.translate_x and self.lights[i].x - self.lights[i].range < love.graphics.getWidth() + self.translate_x
|
|
||||||
and self.lights[i].y + self.lights[i].range > self.translate_y and self.lights[i].y - self.lights[i].range < love.graphics.getHeight() + self.translate_y
|
|
||||||
then
|
|
||||||
local lightposrange = {self.lights[i].x, love.graphics.getHeight() - self.lights[i].y, self.lights[i].range}
|
|
||||||
local light = self.lights[i]
|
|
||||||
self.direction = self.direction + 0.002
|
|
||||||
self.shader:send("lightPosition", {self.lights[i].x - self.translate_x, love.graphics.getHeight() - (self.lights[i].y - self.translate_y), self.lights[i].z})
|
|
||||||
self.shader:send("lightRange", self.lights[i].range)
|
|
||||||
self.shader:send("lightColor", {self.lights[i].red / 255.0, self.lights[i].green / 255.0, self.lights[i].blue / 255.0})
|
|
||||||
self.shader:send("lightSmooth", self.lights[i].smooth)
|
|
||||||
self.shader:send("lightGlow", {1.0 - self.lights[i].glowSize, self.lights[i].glowStrength})
|
|
||||||
self.shader:send("lightAngle", math.pi - self.lights[i].angle / 2.0)
|
|
||||||
self.shader:send("lightDirection", self.lights[i].direction)
|
|
||||||
|
|
||||||
love.graphics.setCanvas(self.lights[i].shadow)
|
|
||||||
love.graphics.clear()
|
|
||||||
|
|
||||||
-- calculate shadows
|
|
||||||
local shadow_geometry = calculateShadows(light, self.body)
|
|
||||||
|
|
||||||
-- draw shadow
|
|
||||||
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.body))
|
|
||||||
love.graphics.setBlendMode("additive")
|
|
||||||
love.graphics.rectangle("fill", self.translate_x, self.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
|
|
||||||
end
|
|
||||||
|
|
||||||
for k = 1, #self.body do
|
|
||||||
if self.body[k].alpha < 1.0 then
|
|
||||||
love.graphics.setBlendMode("multiplicative")
|
|
||||||
love.graphics.setColor(self.body[k].red, self.body[k].green, self.body[k].blue)
|
|
||||||
if self.body[k].shadowType == "circle" then
|
|
||||||
love.graphics.circle("fill", self.body[k].x - self.body[k].ox, self.body[k].y - self.body[k].oy, self.body[k].radius)
|
|
||||||
elseif self.body[k].shadowType == "rectangle" then
|
|
||||||
love.graphics.rectangle("fill", self.body[k].x - self.body[k].ox, self.body[k].y - self.body[k].oy, self.body[k].width, self.body[k].height)
|
|
||||||
elseif self.body[k].shadowType == "polygon" then
|
|
||||||
love.graphics.polygon("fill", unpack(self.body[k].data))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.body[k].shadowType == "image" and self.body[k].img then
|
|
||||||
love.graphics.setBlendMode("alpha")
|
|
||||||
local length = 1.0
|
|
||||||
local shadowRotation = math.atan2((self.body[k].x) - self.lights[i].x, (self.body[k].y + self.body[k].oy) - self.lights[i].y)
|
|
||||||
--local alpha = math.abs(math.cos(shadowRotation))
|
|
||||||
|
|
||||||
self.body[k].shadowVert = {
|
|
||||||
{math.sin(shadowRotation) * self.body[k].imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * self.body[k].imgHeight + (math.cos(shadowRotation) + 1.0) * self.body[k].shadowY, 0, 0, self.body[k].red, self.body[k].green, self.body[k].blue, self.body[k].alpha * self.body[k].fadeStrength * 255},
|
|
||||||
{self.body[k].imgWidth + math.sin(shadowRotation) * self.body[k].imgHeight * length, (length * math.cos(shadowRotation) + 1.0) * self.body[k].imgHeight + (math.cos(shadowRotation) + 1.0) * self.body[k].shadowY, 1, 0, self.body[k].red, self.body[k].green, self.body[k].blue, self.body[k].alpha * self.body[k].fadeStrength * 255},
|
|
||||||
{self.body[k].imgWidth, self.body[k].imgHeight + (math.cos(shadowRotation) + 1.0) * self.body[k].shadowY, 1, 1, self.body[k].red, self.body[k].green, self.body[k].blue, self.body[k].alpha * 255},
|
|
||||||
{0, self.body[k].imgHeight + (math.cos(shadowRotation) + 1.0) * self.body[k].shadowY, 0, 1, self.body[k].red, self.body[k].green, self.body[k].blue, self.body[k].alpha * 255}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.body[k].shadowMesh:setVertices(self.body[k].shadowVert)
|
|
||||||
love.graphics.draw(self.body[k].shadowMesh, self.body[k].x - self.body[k].ox + self.translate_x, self.body[k].y - self.body[k].oy + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setShader(self.shader)
|
|
||||||
|
|
||||||
-- draw shine
|
|
||||||
love.graphics.setCanvas(self.lights[i].shine)
|
|
||||||
self.lights[i].shine:clear(255, 255, 255)
|
|
||||||
love.graphics.setBlendMode("alpha")
|
|
||||||
love.graphics.setStencil(stencils.poly(self.body))
|
|
||||||
love.graphics.rectangle("fill", self.translate_x, self.translate_y, love.graphics.getWidth(), love.graphics.getHeight())
|
|
||||||
|
|
||||||
lightsOnScreen = lightsOnScreen + 1
|
|
||||||
|
|
||||||
self.lights[i].visible = true
|
|
||||||
else
|
|
||||||
self.lights[i].visible = false
|
|
||||||
end
|
|
||||||
|
|
||||||
self.lights[i].changed = self.changed
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update shadow
|
-- update shadow
|
||||||
@ -214,9 +123,7 @@ function light_world:update()
|
|||||||
love.graphics.setColor(255, 255, 255)
|
love.graphics.setColor(255, 255, 255)
|
||||||
love.graphics.setBlendMode("additive")
|
love.graphics.setBlendMode("additive")
|
||||||
for i = 1, #self.lights do
|
for i = 1, #self.lights do
|
||||||
if self.lights[i].visible then
|
self.lights[i]:drawShadow()
|
||||||
love.graphics.draw(self.lights[i].shadow, self.translate_x, self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
self.isShadowBlur = false
|
self.isShadowBlur = false
|
||||||
|
|
||||||
@ -228,9 +135,7 @@ function light_world:update()
|
|||||||
love.graphics.setColor(255, 255, 255)
|
love.graphics.setColor(255, 255, 255)
|
||||||
love.graphics.setBlendMode("additive")
|
love.graphics.setBlendMode("additive")
|
||||||
for i = 1, #self.lights do
|
for i = 1, #self.lights do
|
||||||
if self.lights[i].visible then
|
self.lights[i]:drawShine()
|
||||||
love.graphics.draw(self.lights[i].shine, self.translate_x, self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -243,10 +148,7 @@ function light_world:update()
|
|||||||
love.graphics.setShader()
|
love.graphics.setShader()
|
||||||
love.graphics.setCanvas(self.normalMap)
|
love.graphics.setCanvas(self.normalMap)
|
||||||
for i = 1, #self.body do
|
for i = 1, #self.body do
|
||||||
if self.body[i].type == "image" and self.body[i].normalMesh then
|
self.body[i]:drawPixelShadow()
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
love.graphics.draw(self.body[i].normalMesh, self.body[i].x - self.body[i].nx + self.translate_x, self.body[i].y - self.body[i].ny + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
love.graphics.setColor(255, 255, 255)
|
love.graphics.setColor(255, 255, 255)
|
||||||
love.graphics.setBlendMode("alpha")
|
love.graphics.setBlendMode("alpha")
|
||||||
@ -257,28 +159,7 @@ function light_world:update()
|
|||||||
love.graphics.setShader(self.shader2)
|
love.graphics.setShader(self.shader2)
|
||||||
|
|
||||||
for i = 1, #self.lights do
|
for i = 1, #self.lights do
|
||||||
if self.lights[i].visible then
|
self.lights[i]:drawPixelShadow()
|
||||||
if self.normalInvert then
|
|
||||||
self.normalInvertShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
|
|
||||||
self.normalInvertShader:send('lightColor', {self.lights[i].red / 255.0, self.lights[i].green / 255.0, self.lights[i].blue / 255.0})
|
|
||||||
self.normalInvertShader:send('lightPosition',{self.lights[i].x, love.graphics.getHeight() - self.lights[i].y, self.lights[i].z / 255.0})
|
|
||||||
self.normalInvertShader:send('lightRange',{self.lights[i].range})
|
|
||||||
self.normalInvertShader:send("lightSmooth", self.lights[i].smooth)
|
|
||||||
self.normalInvertShader:send("lightAngle", math.pi - self.lights[i].angle / 2.0)
|
|
||||||
self.normalInvertShader:send("lightDirection", self.lights[i].direction)
|
|
||||||
love.graphics.setShader(self.normalInvertShader)
|
|
||||||
else
|
|
||||||
self.normalShader:send('screenResolution', {love.graphics.getWidth(), love.graphics.getHeight()})
|
|
||||||
self.normalShader:send('lightColor', {self.lights[i].red / 255.0, self.lights[i].green / 255.0, self.lights[i].blue / 255.0})
|
|
||||||
self.normalShader:send('lightPosition',{self.lights[i].x, love.graphics.getHeight() - self.lights[i].y, self.lights[i].z / 255.0})
|
|
||||||
self.normalShader:send('lightRange',{self.lights[i].range})
|
|
||||||
self.normalShader:send("lightSmooth", self.lights[i].smooth)
|
|
||||||
self.normalShader:send("lightAngle", math.pi - self.lights[i].angle / 2.0)
|
|
||||||
self.normalShader:send("lightDirection", self.lights[i].direction)
|
|
||||||
love.graphics.setShader(self.normalShader)
|
|
||||||
end
|
|
||||||
love.graphics.draw(self.normalMap, self.translate_x, self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.setShader()
|
love.graphics.setShader()
|
||||||
@ -310,64 +191,17 @@ function light_world:update()
|
|||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, #self.body do
|
for i = 1, #self.body do
|
||||||
if self.body[i].glowStrength > 0.0 then
|
self.body[i]:drawGlow()
|
||||||
love.graphics.setColor(self.body[i].glowRed * self.body[i].glowStrength, self.body[i].glowGreen * self.body[i].glowStrength, self.body[i].glowBlue * self.body[i].glowStrength)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(0, 0, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.body[i].type == "circle" then
|
|
||||||
love.graphics.circle("fill", self.body[i].x, self.body[i].y, self.body[i].radius)
|
|
||||||
elseif self.body[i].type == "rectangle" then
|
|
||||||
love.graphics.rectangle("fill", self.body[i].x, self.body[i].y, self.body[i].width, self.body[i].height)
|
|
||||||
elseif self.body[i].type == "polygon" then
|
|
||||||
love.graphics.polygon("fill", unpack(self.body[i].data))
|
|
||||||
elseif self.body[i].type == "image" and self.body[i].img then
|
|
||||||
if self.body[i].glowStrength > 0.0 and self.body[i].glow then
|
|
||||||
love.graphics.setShader(self.glowShader)
|
|
||||||
self.glowShader:send("glowImage", self.body[i].glow)
|
|
||||||
self.glowShader:send("glowTime", love.timer.getTime() * 0.5)
|
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
else
|
|
||||||
love.graphics.setShader()
|
|
||||||
love.graphics.setColor(0, 0, 0)
|
|
||||||
end
|
|
||||||
love.graphics.draw(self.body[i].img, self.body[i].x - self.body[i].ix + self.translate_x, self.body[i].y - self.body[i].iy + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.optionRefraction and self.isRefraction then
|
if self.optionRefraction and self.isRefraction then
|
||||||
love.graphics.setShader()
|
love.graphics.setShader()
|
||||||
|
|
||||||
-- create refraction map
|
-- create refraction map
|
||||||
self.refractionMap:clear()
|
self.refractionMap:clear()
|
||||||
love.graphics.setCanvas(self.refractionMap)
|
love.graphics.setCanvas(self.refractionMap)
|
||||||
for i = 1, #self.body do
|
for i = 1, #self.body do
|
||||||
if self.body[i].refraction and self.body[i].normal then
|
self.body[i]:drawRefraction()
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
if self.body[i].tileX == 0.0 and self.body[i].tileY == 0.0 then
|
|
||||||
love.graphics.draw(normal, self.body[i].x - self.body[i].nx + self.translate_x, self.body[i].y - self.body[i].ny + self.translate_y)
|
|
||||||
else
|
|
||||||
self.body[i].normalMesh:setVertices(self.body[i].normalVert)
|
|
||||||
love.graphics.draw(self.body[i].normalMesh, self.body[i].x - self.body[i].nx + self.translate_x, self.body[i].y - self.body[i].ny + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setColor(0, 0, 0)
|
|
||||||
for i = 1, #self.body do
|
|
||||||
if not self.body[i].refractive then
|
|
||||||
if self.body[i].type == "circle" then
|
|
||||||
love.graphics.circle("fill", self.body[i].x, self.body[i].y, self.body[i].radius)
|
|
||||||
elseif self.body[i].type == "rectangle" then
|
|
||||||
love.graphics.rectangle("fill", self.body[i].x, self.body[i].y, self.body[i].width, self.body[i].height)
|
|
||||||
elseif self.body[i].type == "polygon" then
|
|
||||||
love.graphics.polygon("fill", unpack(self.body[i].data))
|
|
||||||
elseif self.body[i].type == "image" and self.body[i].img then
|
|
||||||
love.graphics.draw(self.body[i].img, self.body[i].x - self.body[i].ix + self.translate_x, self.body[i].y - self.body[i].iy + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -377,20 +211,7 @@ function light_world:update()
|
|||||||
self.reflectionMap:clear(0, 0, 0)
|
self.reflectionMap:clear(0, 0, 0)
|
||||||
love.graphics.setCanvas(self.reflectionMap)
|
love.graphics.setCanvas(self.reflectionMap)
|
||||||
for i = 1, #self.body do
|
for i = 1, #self.body do
|
||||||
if self.body[i].reflection and self.body[i].normal then
|
self.body[i]:drawReflection()
|
||||||
love.graphics.setColor(255, 0, 0)
|
|
||||||
self.body[i].normalMesh:setVertices(self.body[i].normalVert)
|
|
||||||
love.graphics.draw(self.body[i].normalMesh, self.body[i].x - self.body[i].nx + self.translate_x, self.body[i].y - self.body[i].ny + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i = 1, #self.body do
|
|
||||||
if self.body[i].reflective and self.body[i].img then
|
|
||||||
love.graphics.setColor(0, 255, 0)
|
|
||||||
love.graphics.draw(self.body[i].img, self.body[i].x - self.body[i].ix + self.translate_x, self.body[i].y - self.body[i].iy + self.translate_y)
|
|
||||||
elseif not self.body[i].reflection and self.body[i].img then
|
|
||||||
love.graphics.setColor(0, 0, 0)
|
|
||||||
love.graphics.draw(self.body[i].img, self.body[i].x - self.body[i].ix + self.translate_x, self.body[i].y - self.body[i].iy + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -488,11 +309,7 @@ end
|
|||||||
function light_world:drawMaterial()
|
function light_world:drawMaterial()
|
||||||
love.graphics.setShader(self.materialShader)
|
love.graphics.setShader(self.materialShader)
|
||||||
for i = 1, #self.body do
|
for i = 1, #self.body do
|
||||||
if self.body[i].material and self.body[i].normal then
|
self.body[i]:drawMaterial()
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
self.materialShader:send("material", self.body[i].material)
|
|
||||||
love.graphics.draw(self.body[i].normal, self.body[i].x - self.body[i].nx + self.translate_x, self.body[i].y - self.body[i].ny + self.translate_y)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
love.graphics.setShader()
|
love.graphics.setShader()
|
||||||
end
|
end
|
||||||
@ -563,7 +380,7 @@ function light_world:drawReflection()
|
|||||||
end
|
end
|
||||||
-- new light
|
-- new light
|
||||||
function light_world:newLight(x, y, red, green, blue, range)
|
function light_world:newLight(x, y, red, green, blue, range)
|
||||||
self.lights[#self.lights + 1] = Light(o, x, y, red, green, blue, range)
|
self.lights[#self.lights + 1] = Light(self, x, y, red, green, blue, range)
|
||||||
self.isLight = true
|
self.isLight = true
|
||||||
return self.lights[#self.lights]
|
return self.lights[#self.lights]
|
||||||
end
|
end
|
||||||
@ -739,98 +556,6 @@ function light_world:getType()
|
|||||||
return "world"
|
return "world"
|
||||||
end
|
end
|
||||||
|
|
||||||
function calculateShadows(light, body)
|
|
||||||
local shadowGeometry = {}
|
|
||||||
local shadowLength = 100000
|
|
||||||
|
|
||||||
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 = vector.normalize(normal)
|
|
||||||
lightToPoint = vector.normalize(lightToPoint)
|
|
||||||
|
|
||||||
local dotProduct = vector.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 = vector.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 = vector.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
|
|
||||||
if not body[i].castsNoShadow 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
|
|
||||||
end
|
|
||||||
|
|
||||||
return shadowGeometry
|
|
||||||
end
|
|
||||||
|
|
||||||
function HeightMapToNormalMap(heightMap, strength)
|
function HeightMapToNormalMap(heightMap, strength)
|
||||||
local imgData = heightMap:getData()
|
local imgData = heightMap:getData()
|
||||||
local imgData2 = love.image.newImageData(heightMap:getWidth(), heightMap:getHeight())
|
local imgData2 = love.image.newImageData(heightMap:getWidth(), heightMap:getHeight())
|
||||||
|
Loading…
Reference in New Issue
Block a user