Löve "Light vs. Shadow" Engine v2

Showcase your libraries, tools and other projects that help your fellow love users.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: Löve "Light vs. Shadow" Engine v2

Post by Magitek »

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.

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
My code:

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

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.
User avatar
Jeeper
Party member
Posts: 611
Joined: Tue Mar 12, 2013 7:11 pm
Contact:

Re: Löve "Light vs. Shadow" Engine v2

Post by Jeeper »

Magitek wrote: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.

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
My code:

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

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.
Personally I have been using V1 for a long time, a couple of weeks ago I decided to switch for similar reasons that you had. I found myself having lower frames and more memory and swapped back. At this point I have fixed most of the issues V1 had anyway, just in case someone else is thinking about swapping for performance, then I would advice against it. V2 does however have fewer issues that need dealing with than V1 and will in general require less tinkering to get it to work.
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: Löve "Light vs. Shadow" Engine v2

Post by bobbyjones »

Why not just make a pull request with your memory optimizations and other optimizations
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: Löve "Light vs. Shadow" Engine v2

Post by Magitek »

Jeeper wrote: Personally I have been using V1 for a long time, a couple of weeks ago I decided to switch for similar reasons that you had. I found myself having lower frames and more memory and swapped back. At this point I have fixed most of the issues V1 had anyway, just in case someone else is thinking about swapping for performance, then I would advice against it. V2 does however have fewer issues that need dealing with than V1 and will in general require less tinkering to get it to work.
My project is too intertwined to make a complete jump to v2, but I think it's worth swapping this particular function from v1->v2->removal of vector class. The v2 version is a lot less verbose, and with the vector class removed, generates less memory trash than v1 for shadows.

If you happen to have a log/code of v1 issues/fixes I'd love to hear about them, because so far I haven't optimized much except shadows and I'm struggling to keep the game above 60 FPS.
bobbyjones wrote:Why not just make a pull request with your memory optimizations and other optimizations
I have enough trouble working on my own project without hacking someone elses work (I'm still primarily using v1). The engine works fine in less complicated examples which is probably what most people are using it for. If I had time, I'd go through the whole project and remove every table and sign operator but I don't.
User avatar
Guard13007
Party member
Posts: 132
Joined: Sat Oct 25, 2014 3:42 am
Location: Internet, USA
Contact:

Re: Löve "Light vs. Shadow" Engine v2

Post by Guard13007 »

Magitek wrote:I have enough trouble working on my own project without hacking someone elses work (I'm still primarily using v1). The engine works fine in less complicated examples which is probably what most people are using it for. If I had time, I'd go through the whole project and remove every table and sign operator but I don't.
Maybe I'm misunderstanding, but you've rewritten a single function here and it has massively improved things? It would literally take 5 minutes for you to create a fork, upload that single change, click pull request, and done. I'm sorry if you don't even have a spare 5 minutes, but I honestly don't see how it would be a problem.
zell2002
Citizen
Posts: 75
Joined: Sun Feb 23, 2014 9:22 pm

Re: Löve "Light vs. Shadow" Engine v2

Post by zell2002 »

Hey guys

This continuation of the 'light vs shadow' lib is cool !

Quick question though, when I place 2 shapes, one behind the other, then place a light in front of one, they both glow - rather than what i was expecting which would be the first shape lights up but not the one behind it
User avatar
Imaculata
Party member
Posts: 102
Joined: Mon Aug 10, 2015 2:51 pm

Re: Löve "Light vs. Shadow" Engine v2

Post by Imaculata »

I'm eager to try an updated version of this library. Because I had a go at the original version, and it immediately brought my game to a crawl. So the code can definitely use some cleaning up.
User avatar
Guard13007
Party member
Posts: 132
Joined: Sat Oct 25, 2014 3:42 am
Location: Internet, USA
Contact:

Re: Löve "Light vs. Shadow" Engine v2

Post by Guard13007 »

zell2002, let me see if I'm understanding you right this time. You're saying you have a problem with the "top" or I guess the "inside" of an object being lit up behind another object from the light's perspective, not the shadows themselves.

In other words, your problem is like what's going on on the right side of this image: https://love2d.org/imgmirrur/AugNYR8.png

I think there's a way to code it to fix this, unfortunately it's been a while since I worked with it, so I'm not sure what it would be. :/
zell2002
Citizen
Posts: 75
Joined: Sun Feb 23, 2014 9:22 pm

Re: Löve "Light vs. Shadow" Engine v2

Post by zell2002 »

Guard13007 wrote:zell2002, let me see if I'm understanding you right this time. You're saying you have a problem with the "top" or I guess the "inside" of an object being lit up behind another object from the light's perspective, not the shadows themselves.

In other words, your problem is like what's going on on the right side of this image: https://love2d.org/imgmirrur/AugNYR8.png

I think there's a way to code it to fix this, unfortunately it's been a while since I worked with it, so I'm not sure what it would be. :/
hi, i think youve got it. basically in that image if you imagine another shape behind the shape being lit, so to the right and thus IN the shadows, it currently still gets lit by that light

ive begun looking into the lib, but i must admit - it's a bit much for me, struggling to make head/tail of it all :/
if there is a fix, that would be amazing
zell2002
Citizen
Posts: 75
Joined: Sun Feb 23, 2014 9:22 pm

Re: Löve "Light vs. Shadow" Engine v2

Post by zell2002 »

Just to clarify :
https://love2d.org/imgmirrur/OiPKMwK.png

the bottom wall I dont think should light up

maybe some would say this is too specific, but even in the "complex" demo if you place 2 shapes one behind the other and shine a light at them the one furthest away lights up as if the first shape doesnt exists
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest