Has anyone discovered a good technique to animate Point Lights?

Hi all,

I’m currently experimenting with point lights, and from what I can tell, the ideal usage for these (in a game anyway), would be to have them ‘follow a sprite’ (in a Dungeon Crawler for example).

The thing is, it’s difficult to make them truly dynamic because pointLight.pos (position) of X,Y,Z are relative to the fill-object’s dimensions NOT the screen co-ordinates, so if you have a background tiles-set for example, calculating lightPos is extremely difficult especially if you want the pointLight to follow a sprite.

I found this thread recently (it uses directional lights, but the concept is the same): 

https://forums.coronalabs.com/topic/55910-applying-a-light-to-multiple-objects-with-normal-maps/

You’ll see on line 19 that the direction has been calculated based on the Developer’s light source:

somaList[i].fill.effect.dirLightDirection = { sunX, sunY, 0.5 }

But I just don’t see how this could work, as translating the ‘X/Y’ co-ordinates to anything other than percentage values is a complete no-no.

So, in a a nutshell, has anyone found a way of relating the pointLight position to co-ordinates that are EXTERNAL of the fill object’s parameters?

I’ve looked, hard, and I’m surprised at the lack of code examples with regards to composites and shaders, it’s a toughy… Any help would be greatly appreciated.

Regards

C

Hey Caithan,

this is a field I don’t have much experience with, but I want to share my thoughts with ou anyways.

The main problem seems to be, that “normalMapWith1PointLight” and “normalMapWith1DirLight” do not except values that are outside of there texture space (the docs say only values between 0 and 1 are possible for x and y).  So using realtime lighting on several objects seems impossible.

As these shaders are just shaders like any others, it should be possible to rewrite them and make it possible to place the light source outside of the texture. (you would achieve that with values that are smaller than 0 or bigger than 1)

The general issue, that the effect cordinates are allways in texture space (percentages) is the easiest to overcome. All the values needed to estimate them from the screen cordinates are there (x,y cordinates of light source and the enlighted object, size of the enlightened object etc.). One general thing you should also keep in mind is using a snapshot for all the enlightened objects, as it is way faster to use the shader on one big object than on many smaller ones.

Hope you find a solution :slight_smile:

Hey C, I was involved in the thread you mentioned above.  I have a solution that works as long as your objects don’t rotate.

Instead of using a point of light, use a direction of light on each object - referencing the position of the light source.

  1.  Use directional light (not 1 point light) on all of the tiles (assuming we are talking about dungeon tiles).

  2.  Calculate the angle to the light source (you can start with degrees as it’s conceptually easier than radians).

  3.  Convert degrees to radians and evaluate the quadrant position for +/- values (remember the y-axis is reversed in Corona)

  4.  math.cos(radians) = lightX (+/- determined by quadrant position)

  5.  math.sin(radians)  = lightY (+/- determined by quadrant position)

      local tiles = {tile1, tile2, tile3} – table of tiles   for i=1,#tiles do           tiles[i].fill.effect.dirLightDirection = { lightX, lightY, 0.5 } – x, y, z values for the Normal Map ; applied to each object end  

            

Then use Runtime:addEventListener( “enterFrame”, yourLightUpdateFunction ) to update the tiles every frame or every few frames.     

Depending on how many tiles you have this could be processor heavy.  I got this working well with about 50 moving objects updating every frame.  You can do every 3rd frame or alternate updating odd and even tiles to ease off on the processor load.

*I didn’t check the above code but the concept is solid and tested.

Good luck!

Jonathan

Someone else in the world cares about normal lighting!

If I recall, the 0-1 restriction Corona claims on the docs page isn’t correct. You can set the X or Y to pretty much anything. Though I did end up rolling my own normal lighting filter (so that I could customize it more), Corona’s normal lighting is pretty great. Give it a try.

[Edit:] Calculating the relative-to-object-size position of the normal light isn’t all that hard, either:

local normalizedPositionX = ((light.x - objectToBeLit.x) \* objectToBeLit.xScale) / objectToBeLit.width local normalizedPositionY = ((light.y - objectToBeLit.y) \* objectToBeLit.yScale) / objectToBeLit.height
  • Caleb

Caleb,

I want to make something with your Dusk Engine when I get a chance.  I played around with it a little - nice work!

Caithan,

If you need more help with the 1 point lighting let me know.  I worked on it last year but then decided not to use it in my current app so I have the concept in my head but the code is who knows where.  The solution involves several trig functions which I can also help you with if it’s been a while since trig class.

I have another idea!

2 points of light, so you might have a torch on the wall and a torch in your hand.  All the art assets are cloned in place with each clone being set to 50% alpha (plus a normal lighting file for each one).  The directions and distances are calculated and directional lighting is applied as above, only this time you do it twice - once for each clone.  The lights could even be different hues - red light, orange light, something like that.

Hmmm. . . . could it work?

-Jonathan

Hey Caithan,

this is a field I don’t have much experience with, but I want to share my thoughts with ou anyways.

The main problem seems to be, that “normalMapWith1PointLight” and “normalMapWith1DirLight” do not except values that are outside of there texture space (the docs say only values between 0 and 1 are possible for x and y).  So using realtime lighting on several objects seems impossible.

As these shaders are just shaders like any others, it should be possible to rewrite them and make it possible to place the light source outside of the texture. (you would achieve that with values that are smaller than 0 or bigger than 1)

The general issue, that the effect cordinates are allways in texture space (percentages) is the easiest to overcome. All the values needed to estimate them from the screen cordinates are there (x,y cordinates of light source and the enlighted object, size of the enlightened object etc.). One general thing you should also keep in mind is using a snapshot for all the enlightened objects, as it is way faster to use the shader on one big object than on many smaller ones.

Hope you find a solution :slight_smile:

Hey C, I was involved in the thread you mentioned above.  I have a solution that works as long as your objects don’t rotate.

Instead of using a point of light, use a direction of light on each object - referencing the position of the light source.

  1.  Use directional light (not 1 point light) on all of the tiles (assuming we are talking about dungeon tiles).

  2.  Calculate the angle to the light source (you can start with degrees as it’s conceptually easier than radians).

  3.  Convert degrees to radians and evaluate the quadrant position for +/- values (remember the y-axis is reversed in Corona)

  4.  math.cos(radians) = lightX (+/- determined by quadrant position)

  5.  math.sin(radians)  = lightY (+/- determined by quadrant position)

      local tiles = {tile1, tile2, tile3} – table of tiles   for i=1,#tiles do           tiles[i].fill.effect.dirLightDirection = { lightX, lightY, 0.5 } – x, y, z values for the Normal Map ; applied to each object end  

            

Then use Runtime:addEventListener( “enterFrame”, yourLightUpdateFunction ) to update the tiles every frame or every few frames.     

Depending on how many tiles you have this could be processor heavy.  I got this working well with about 50 moving objects updating every frame.  You can do every 3rd frame or alternate updating odd and even tiles to ease off on the processor load.

*I didn’t check the above code but the concept is solid and tested.

Good luck!

Jonathan

Someone else in the world cares about normal lighting!

If I recall, the 0-1 restriction Corona claims on the docs page isn’t correct. You can set the X or Y to pretty much anything. Though I did end up rolling my own normal lighting filter (so that I could customize it more), Corona’s normal lighting is pretty great. Give it a try.

[Edit:] Calculating the relative-to-object-size position of the normal light isn’t all that hard, either:

local normalizedPositionX = ((light.x - objectToBeLit.x) \* objectToBeLit.xScale) / objectToBeLit.width local normalizedPositionY = ((light.y - objectToBeLit.y) \* objectToBeLit.yScale) / objectToBeLit.height
  • Caleb

Caleb,

I want to make something with your Dusk Engine when I get a chance.  I played around with it a little - nice work!

Caithan,

If you need more help with the 1 point lighting let me know.  I worked on it last year but then decided not to use it in my current app so I have the concept in my head but the code is who knows where.  The solution involves several trig functions which I can also help you with if it’s been a while since trig class.

I have another idea!

2 points of light, so you might have a torch on the wall and a torch in your hand.  All the art assets are cloned in place with each clone being set to 50% alpha (plus a normal lighting file for each one).  The directions and distances are calculated and directional lighting is applied as above, only this time you do it twice - once for each clone.  The lights could even be different hues - red light, orange light, something like that.

Hmmm. . . . could it work?

-Jonathan