2D Dynamic Shadows

Just wanted to share the results of my experiment with dynamic 2D realtime shadows.

I did some videos to show you the results on YouTube. Here is the latest one for version 1.31:

http://youtu.be/raCsLiGWjBs

Complete project at BitBucket:

https://bitbucket.org/reneaye/corona-2d-shadow-system/

Do a real clone  with console or i.e. SourceTree or the whole repository gets not resolved correctly. Do not use BitBuckets website download button.

Or for convenience here is a complete archive to download, but it might not be the bleeding edge version:

Shadow System v1.1 (30.12.2014)

Shadow System v1.31 (09.01.2014)

If you look closely, you will see a problem I call the “Lucky Luke Problem”: when the objects moves/rotates fast the shadow is slower than the object updates it’s position. Don’t know how to solve this, since the shadows get calculated on a Runtime “enterframe” event (it’s not possible doing it faster, isn’t it?)

Any ideas how to solve this? Maybe there is is a way to optimize the time when the shadows gets calculated?

Very cool!

Regarding the Lucky Luke problem, drawing your shapes using the nearest cube corner point “in the middle” of your contact shadow instead of the farthest will help a little already, I think. Are the boxes controlled by a player, or automatically? If the latter, why not move the boxes within the same enterFrame event? Everything in this code block will be drawn together before the frame is updated I believe, so things 'll move more or less in unison.

The big crate gets moved by a transition.to. The vertices at the four corners to calculate the shadow from are child objects of this crate that gets moved with the transition.to method. It seems that the child objects gets updated a bit later after the parent object.

Moving the tranistion.to directly into the shadow update method does not change the Lucky Luke effect :frowning:

I think I will clean up the code a bit and put it to GitHub. Maybe someone else interested in shadows is able to optimize.

Looks great.  I’m looking forward to seeing this on gitHub.

Ok I cleaned up most of the code, added some documentation.

I’ve created a repository on BitBucket. You can download it here:

https://bitbucket.org/reneaye/corona-2d-shadow-system/

Thanks for sharing this.  It works well in the simulator and on hardware (even an older gen1 Nexus 7).

I did have to make some small adjustments however.  Lua is case-sensitive and some of your require statements used the wrong cases for file names.  I merely updated all directory and file names to camel-case and then modified the code to use the same case.

After that… bingo.  No prob.

Again, thanks for sharing this.  If I find any optimizations or a solution to the ‘Lucky Luke’ issue I’ll post back.  

Ah, did not test it on hardware yet. I will add the changes to the repository. Thank you for the hint!

Yes, please, if you have any ideas about the lagging shadow polygons, let me know.

Ok, I updated the repo. Should be running on devices out of the box.

Really, really cool.

  • Caleb

Would increasing the frame rate fix it?

The example on BitBucket is already set to 60 fps. So, unfortunately not :frowning:

The Lucky Luke effect does only appear if I use transition.to() to move/rotate the object. I.e. if I drag the object (the crates and lights in the example are draggable) or if I rotate a crate with 

crate1.rotation = crate1.rotation + 5

in an update timer then the shadows are fine.

It seems the transition.to() let the objects updates somehow different which leads to the Lucky Luke effect.

This is a fantastic library. Well done and thank you.

I was thinking that perhaps the Lucky Luke (why that name, in particular?) problem is due to the enterFrame executing before the code executed by the transition library, yet before the screen is actually updated. Have you tried using a timer which executes at 120 times a second? (transition.to does not have a per-frame event listener, unfortunately.)

Ah good idea with the timer! I will try that.

You know the Lucky Luke comic character? Maybe it’s more known in Europe (where are you from?). Lucky Luke is a Western hero that can shoot faster than is own shadow :slight_smile:

Ah, I get it. I didn’t, but there was a demo for a game called that on the Archimedes a long time ago.

Ok, just checked to update the shadows 120 times a second. This would be a timer.perfomWithDelay with a delay set to 8.333, right?

(8.333 * 120 = 1000, roundabout).  But the shadows are still lagging when using transitions :( 

It’s really a shame that transition.* doesn’t offer a per-event listener.

How about a special “should this be an instant-update light” option that sets the metatable (special setting because setting the metatable results in a slower table)?

Pseudo-code (within shadows library):
[lua]
if thisLightShouldBeInstantUpdate then
local mt = getmetatable(thisLight)
local prevNewIndex = mt.__newindex
mt.__newindex = function(self, k, v)
prevNewIndex(self, k, v) – Use the original newindex function
if k == “x” or k == “y” then
self.update() – Whatever the “update this light” function is named
end
end
end
[/lua]

The above code should listen for setting of the light’s x or y value, then update the light when that happens. That way, the light will update each time it’s moved, not just on an enterFrame basis.

[lua]
light.x, light.y = 500, 500 – Bing! The light updates!
[/lua]

Of course, you probably still want the enterFrame listener to catch other objects moving.

You could expand this idea if the problem is occurring when any object moves, not just the light, and do a __newindex to update the whole scene’s light; I don’t know when this problem is happening, exactly.

Lua metatables are you friend!

  • Caleb

Thank you for your idea, Caleb. I will definitely take a look at the metatables approach. But first I have to read about Lua metatables. I does not know anything about it.

Hi everybody,

In the Corona Geek Show #122 Charles gave me the opportunity to present the 2D shadow system. Now I updated the source code at the BitBucket repo to v1.1 which contains the latest features you can see in that Corona Geek issue.

New features are

  • Added circle shape support
  • Added support for multiple shapes per shadow caster
  • dded support for CodeAndWeb’s PhysicsEditor to create complex shapes
  • Added support for a shadow length factor. Now shadows can be longer or shorter per light source setting. (Simulates the height of the light source)
  • Shadows intensity can be changed independently from light source intensity. Per default it is the same, but if you want to make the shadows brighter without changing the appearance of the light.
  • Support for concave shapes (using multiple convex shapes)
  • Support for counter clockwise vertex shapes
  • Fixed a lense flare texture (borders were visible)
  • Some polishing to background and shadow caster objects (especially for the Corona Geek Show #122 :slight_smile:

To keep the compatibility to Coronas Starter Edition I implemented a image buffer technique. This means: drawing all shadow stuff on a white background, then capturing this greyscale image as a display object, hide all shadow polygon objects and finally drawing the captured image on to the screen. This might be a bit slower and I could imagine this way I use more texture memory. But at this I time I think it’s the only way to support multi shape objects with Corona Starter Edition.

 

Please let me know how the performance is going.
@roaminggamer Ed, maybe you could use your test scene you showed at Corona Geek (now it is officially a benchmark scene for the shadow system :lol: ) and let me know how it performs.

 

Oh, and Ed Maurina also found a way to use transition.to() and avoid the Lucky Luke (lagging shadows) problem: do not let the transition change the x and y position of the shadow caster object directly. Instead use some interim variables to do the transition to (yes you can do transitions on variables, it must not be a display object). And then update the shadow caster’s x/y position values to these interim variables in an enterFrame event for example. Good Idea! Thank you Ed.