Applying a light to multiple objects with normal maps

I was hoping to use Graphics 2.0’s support for normal maps to provide some slick 3d effects to my game.

But it looks like:

  1. I can only set directional or point lighting per-object, instead of per-scene. So if I want a light to move through a scene and create awesome-looking 3d lighting effects on all of my objects, I need to calculate the relative location of the light to every single object and set that parameter on each. I’m worried this will be slow.
  2. It’s not possible to use Corona’s animation engine on lighting position. Feeding object.fill.effect.pointLightPos into transition.to, for example, spits out errors.

Is my assessment correct? I was hoping to create an effect where an object emits light, animating through the scene and dynamically lighting the surrounding objects.

Hey Secret Man,

I’m working on a similar endeavor and was very worried about performance, so much so that I almost didn’t even bother trying.  However, I’m glad I did.  I have a scene with hundreds of objects moving about independently and I used a timer.performWithDelay to update the shading for every object via fill.effect.dirLightDirection - 10x/second.

Much to my surprise, I have not, repeat, have not experienced a significant decrease in the frame rate.  Give it a shot!  The problem I have encountered is that when objects rotate, their shading does not reflect their rotation - it still shades as if the object never rotated.

My fear is that recalculating the rotation will take more bandwidth than the super-efficient Graphics 2.0 normal mapping did.  Fingers crossed. . . 

Good luck with your scenes.

Jonathan

Wow, that is surprising. Thanks for providing this info!

What devices did you test on to validate performance?

Do you care to share a code snippet for how you calculated the position of the light for each object? I have to admit I haven’t thoroughly researched exactly what dirLightDirection means or how to calculate it yet.

I haven’t tested it on devices yet but I’m using a performance meter module for the Corona Simulator that I find very helpful 

[url=[https://github.com/pancsoftware/performancemeter.git](https://github.com/pancsoftware/performancemeter.git)]

In my app I have 100 - 200 objects (life forms) interacting with one another and I thought it would be cool to introduce light and dark cycles.  I made a sun module (sun.lua) and in it a sun rotates off screen around the viewable area.  I move the sun with a method called “moveSun()”.  moveSun() moves the sun in a circle around the center of the screen and returns the x and y positions of the sun as sine an cosine values for use in the object fill method -  object.fill.effect.dirLightDirection = { x, y, z }

[url=http://docs.coronalabs.com/guide/graphics/effects.html]

[lua]

local sunTimer = timer.performWithDelay( 100, function() -- inline function repeats 10x/sec local physicsState = ui.getPhysicsState() -- get current physics state if (physicsState == "play") then -- if physics state is "play" e.i. not paused local sunX, sunY = sun.moveSun() --[[calls the moveSun() method from the sun module (require file) which: 1) rotates the sun around the center by a set number of degrees 2) compares the position of the sun to the center (in degrees) 3) converts postion degrees to radians and gets quadrant info for +/- values 4) math.cos(radians) = sunX 5) math.sin(radians) = sunY 6) returns sunX, sunY --]] for i=1,#somaList do -- somaList is a list that stores the objects if (somaList[i].alive == true) then -- if the object is not dead somaList[i].fill.effect.dirLightDirection = { sunX, sunY, 0.5 } -- x, y, z values for the Normal Map ; applied to each object end end end end, 0) -- end inline function and set repeat to infinite

[/lua]

My frame rates start of get little glitches when I get to about 100 objects and it becomes very noticeable by 150 objects.

Unfortunately, the method I wrote to fix the rotation problem I mentioned above decreases performance significantly.  The frame rate glitches around 50 objects.  I think I can find a way to refine it but, for my app, I doubt it will be clean enough to be useful.  I’m thinking I will use the normal map to create a sense of depth that isn’t true to the scene lighting and then use object.soma.fill.effect.ambientLightIntensity to change the mood of the lighting.  

Only people with a degree of art training or a high level of observation will notice this imperfection.  With Hollywood lighting casting improbably shadows on everything we watch, I think most people are desensitized to true lighting and won’t notice my trickery ; )

I’m going to spend one more day on this n-map rotation problem and then I’m going to move onto the other tasks.

Let me know if you make any discoveries!

Jonathan

By the way, I’m using Sprite Illuminator to make the normal maps.  https://www.codeandweb.com/spriteilluminator

I really like Code and Web and also use Texture Packer and Physics Editor which have each saved me tons of time!

Jonathan

Quick note for the above comment: We did a rebranding recently, so the link has been updated to the below:

https://github.com/pancinteractive/performancemeter

Also, I simply adapted an older performance meter module from Lerg, who is a wizard. Just wanted to make sure he got a shout out!

Hey Secret Man,

I’m working on a similar endeavor and was very worried about performance, so much so that I almost didn’t even bother trying.  However, I’m glad I did.  I have a scene with hundreds of objects moving about independently and I used a timer.performWithDelay to update the shading for every object via fill.effect.dirLightDirection - 10x/second.

Much to my surprise, I have not, repeat, have not experienced a significant decrease in the frame rate.  Give it a shot!  The problem I have encountered is that when objects rotate, their shading does not reflect their rotation - it still shades as if the object never rotated.

My fear is that recalculating the rotation will take more bandwidth than the super-efficient Graphics 2.0 normal mapping did.  Fingers crossed. . . 

Good luck with your scenes.

Jonathan

Wow, that is surprising. Thanks for providing this info!

What devices did you test on to validate performance?

Do you care to share a code snippet for how you calculated the position of the light for each object? I have to admit I haven’t thoroughly researched exactly what dirLightDirection means or how to calculate it yet.

I haven’t tested it on devices yet but I’m using a performance meter module for the Corona Simulator that I find very helpful 

[url=[https://github.com/pancsoftware/performancemeter.git](https://github.com/pancsoftware/performancemeter.git)]

In my app I have 100 - 200 objects (life forms) interacting with one another and I thought it would be cool to introduce light and dark cycles.  I made a sun module (sun.lua) and in it a sun rotates off screen around the viewable area.  I move the sun with a method called “moveSun()”.  moveSun() moves the sun in a circle around the center of the screen and returns the x and y positions of the sun as sine an cosine values for use in the object fill method -  object.fill.effect.dirLightDirection = { x, y, z }

[url=http://docs.coronalabs.com/guide/graphics/effects.html]

[lua]

local sunTimer = timer.performWithDelay( 100, function() -- inline function repeats 10x/sec local physicsState = ui.getPhysicsState() -- get current physics state if (physicsState == "play") then -- if physics state is "play" e.i. not paused local sunX, sunY = sun.moveSun() --[[calls the moveSun() method from the sun module (require file) which: 1) rotates the sun around the center by a set number of degrees 2) compares the position of the sun to the center (in degrees) 3) converts postion degrees to radians and gets quadrant info for +/- values 4) math.cos(radians) = sunX 5) math.sin(radians) = sunY 6) returns sunX, sunY --]] for i=1,#somaList do -- somaList is a list that stores the objects if (somaList[i].alive == true) then -- if the object is not dead somaList[i].fill.effect.dirLightDirection = { sunX, sunY, 0.5 } -- x, y, z values for the Normal Map ; applied to each object end end end end, 0) -- end inline function and set repeat to infinite

[/lua]

My frame rates start of get little glitches when I get to about 100 objects and it becomes very noticeable by 150 objects.

Unfortunately, the method I wrote to fix the rotation problem I mentioned above decreases performance significantly.  The frame rate glitches around 50 objects.  I think I can find a way to refine it but, for my app, I doubt it will be clean enough to be useful.  I’m thinking I will use the normal map to create a sense of depth that isn’t true to the scene lighting and then use object.soma.fill.effect.ambientLightIntensity to change the mood of the lighting.  

Only people with a degree of art training or a high level of observation will notice this imperfection.  With Hollywood lighting casting improbably shadows on everything we watch, I think most people are desensitized to true lighting and won’t notice my trickery ; )

I’m going to spend one more day on this n-map rotation problem and then I’m going to move onto the other tasks.

Let me know if you make any discoveries!

Jonathan

By the way, I’m using Sprite Illuminator to make the normal maps.  https://www.codeandweb.com/spriteilluminator

I really like Code and Web and also use Texture Packer and Physics Editor which have each saved me tons of time!

Jonathan

Quick note for the above comment: We did a rebranding recently, so the link has been updated to the below:

https://github.com/pancinteractive/performancemeter

Also, I simply adapted an older performance meter module from Lerg, who is a wizard. Just wanted to make sure he got a shout out!