Re: Löve "Light vs. Shadow" Engine v2
Posted: Fri May 01, 2015 6:53 am
Well I've been using the v1 engine for quite some time and I would've liked to say everything was going well, but I think I spent the majority of my time fighting it. It was the basis for my current project but it simply didn't scale up without issues.
The code has some Lua gotcha issues, particularly related to memory trash and abuse of the # operator. You don't notice typically notice these issues until things come crashing down unfortunately, which they did. The engine is very cool but I think I spent more time hacking it than using it as intended (partially my fault for introducing it late I guess).
I thought the issue would have been fixed had I upgraded to v2 but I couldn't have been more wrong.
V1: 120fps 172 shadow casters create 8MB/s of memory trash.
V2: 120fps 172 shadow casters create 55MB/s of memory trash!
I thought 8MB/s was pretty bad, mostly because I have not consolidated shadow masses yet, but 55MB/s is out of this world.
This code is mostly flawed because the vector class creates and destroys tables and you're doing it a thousand times each frame.
My code:
Now it just generates just ~1.5MB/s of trash total, as opposed to 55. (note height performance omission however, and the math might be wrong.. I'm not done with it yet)
I figured I would mention this issue because it feels awfully out of line for what is going on.
Please be more careful with the # operator for performance reasons (just store the length every frame) and table creation / using C-style classes in performance-heavy situations.
The code has some Lua gotcha issues, particularly related to memory trash and abuse of the # operator. You don't notice typically notice these issues until things come crashing down unfortunately, which they did. The engine is very cool but I think I spent more time hacking it than using it as intended (partially my fault for introducing it late I guess).
I thought the issue would have been fixed had I upgraded to v2 but I couldn't have been more wrong.
V1: 120fps 172 shadow casters create 8MB/s of memory trash.
V2: 120fps 172 shadow casters create 55MB/s of memory trash!
I thought 8MB/s was pretty bad, mostly because I have not consolidated shadow masses yet, but 55MB/s is out of this world.
This code is mostly flawed because the vector class creates and destroys tables and you're doing it a thousand times each frame.
Code: Select all
body.lua
function body:drawPolyShadow(light)
local lightPosition = vector(light.x, light.y)
local lh = lightPosition * self.zheight
local height_diff = (self.zheight - light.z)
if height_diff == 0 then -- prevent inf
height_diff = -0.001
end
for i = 1, #self.data, 2 do
local vertex = vector(self.data[i], self.data[i + 1])
local nextVertex = vector(self.data[(i + 2) % #self.data], self.data[(i + 2) % #self.data + 1])
local startToEnd = nextVertex - vertex
if vector(startToEnd.y, -startToEnd.x) * (vertex - lightPosition) > 0 then
local point1 = (lh - (vertex * light.z))/height_diff
local point2 = (lh - (nextVertex * light.z))/height_diff
love.graphics.polygon("fill",
vertex.x, vertex.y, point1.x, point1.y,
point2.x, point2.y, nextVertex.x, nextVertex.y)
end
end
end
Code: Select all
function drawPolyShadow(body, light)
local lh_x = light.x * body.z
local lh_y = light.y * body.z
local height_diff = (body.z - light.z)
if height_diff == 0 then -- prevent inf
height_diff = -0.001
end
local blen = #body.data --should probably be stored on the body instead of counted every time
for i = 1, blen, 2 do
local v_x, v_y = body.data[i], body.data[i+1]
local nv_x, nv_y = body.data[(i + 2) % blen], body.data[(i + 2) % blen + 1]
local p1_x, p1_y = (lh_x - (v_x * light.z))/height_diff, (lh_y - (v_y * light.z))/height_diff
local p2_x, p2_y = (lh_x - (nv_x * light.z))/height_diff, (lh_y - (nv_y * light.z))/height_diff
love.graphics.polygon("fill",
v_x, v_y, p1_x, p1_y,
p2_x, p2_y, nv_x, nv_y)
end
end
I figured I would mention this issue because it feels awfully out of line for what is going on.
Please be more careful with the # operator for performance reasons (just store the length every frame) and table creation / using C-style classes in performance-heavy situations.