How To: Pseudo-Dynamic lighting approach on actors, including Distance Lighting

DevirosDeviros Member, PRO Posts: 87
edited December 2015 in Community Tutorials

Dynamic Lighting

So - Dynamic lighting is one thing that can make a huge difference in how engaged a player is with a game, it can really add to the immersion level, and it's one of the things that Game Salad simply isn't capable of at the moment, so i started playing around, trying to see if there was some way to work around this, and i've come up with something that kind of works (at least, for the moment, for round objects). I'm going to keep refining this and hopefully have something far more workable, but i believe that it's a good start.

First off, here's a preview of what i've started to do:

So - as you can see as mister happy green ball there moves around the scene, his shine and shadow rotate to face the light. (yes, i know this only applies to round objects, right now, i'll explain my potential solution for complex objects, as awful as it's going to be, shortly).

The way i've done this is with three actors, that make up the character, ball at the bottom, then shadow layer, then eyes:

The green ball is the 'master', and the shadow actor and the eyes are both constrained to the ball's center. The shadow is then constrained via vector-to-angle to the very-square-sun there in the centerish of the scene, as such:

As the left and right keys are held down, the ball's angular velocity is increased (exponentially, because demo.), and the linear velocity is constrained the negative of the angular velocity, halved. This allows him to move, and, as the eyes are rotationally constrained to the ball, they rotate as well, in time with the ball's rotation.

Clever use of tables would allow for an infinite (though somewhat resource intensive) number of characters on the screen that obey these rules - to a central light source. Obviously this doesn't work with multiples, but using the additive property (and getting rid of the shadow) along with a second reflection actor creates a somewhat believable effect:

So - on to complex shapes! In the next post, this will get full treatment, but here's a bit of explanation:

You'd need to create a 'lighting map' (not really, but bear with me) that has the possible lighting result from every angle of the character. You could do this for all 360 degrees, but that would be... awful. Instead, you would be better served with creating a lighting overlay for every 10-20 degrees or so (and dealing with a slight jump between each), and put these in a table, and then for every vector to angle calculation (between the lightsource and the lightmap actor), you apply the pertinent image to the lighting actor.

This method still works for multiple light sources, and would work just as well with dynamically spawned actors. This does get complex, however, but it's still totally doable. You just need lots of notes and a great organizational system.

I.E.

If Actor_In_Position_one {
if ( 0 < VectorToAngleResult > 9 ) { constrain image to tableCellValue(TBL_Actor_1_LightMap, 1, 1)}

if ( 10 < VectorToAngleResult > 19 ) { constrain image to tableCellValue(TBL_Actor_1_LightMap, 1, 2)}
}

If Actor_In_Position_two {
if ( 0 < VectorToAngleResult > 9 ) { constrain image to tableCellValue(TBL_Actor_1_LightMap, 2, 1)}

if ( 10 < VectorToAngleResult > 19 ) { constrain image to tableCellValue(TBL_Actor_1_LightMap, 2, 2)}
}

etcetera.

Dev.

Comments

  • DevirosDeviros Member, PRO Posts: 87
    edited December 2015

    And now, the continuing Saga of the Dynamic Lighting!

    Complex Shapes

    Complex shapes add a bit of complexity (duh, haha), and in the previous post, I touched on them a little bit. I've also made the lighting itself 'simple (just blocks of color) to make it clear what's going on. Take a look at the video example below:

    For the sake of this demonstration and keeping it easy to explain, I've kept the number of display positions to 8, and am using hardcoded rules rather than tables, as this makes it easier to display what's going on.

    Basically, what i've done here, is create 8 images that overlay mister happy box, and then calculate the angle (vectorToAngle) between the Box's light layer to the squaresun.

    You can see the (simplified) code in this video:

    The reason that I'm adding 180 to the angle calculation is to keep the angle above 0 - makes it easier to math.

    Ideally, you'd want to do this with tables and image constraints, so you could have a table with 360 rows, and an image in each row, and then just constrain the image as such:

    constrain image to tableCellValue(TBL_Actor_1_Light_Layer, INT_Angle, 2)

    However, in this instance I wanted to show exactly how it worked.

    If you didn't have 360 individual lighting images (and you shouldn't, seriously, that would be awful) you would just copy and paste the same image across multiple angles:

        TBL_Actor_1_Light_Layer
    
        Angle             ImageName
        1                   image_one
        2                   image_one
        3                   image_one
        4                   image_one
        5                   image_one
        6                   image_two
        7                   image_two
        8                   image_two
        9                   image_two
        10                  image_two
    
  • DevirosDeviros Member, PRO Posts: 87

    The Saga Continues!

    Distance Based Lighting

    So - all that lighting is well and good, right? But what about if you're far away from the object de light?

    Well, how's this look?

    This is actually extremely simple: We're simply adjusting the opacity of the lighting layer according to the distance from the lighting object, as such:

    If you can't see what's going on, here's what we have:

    First, we constrain our storage values for distance to the equated distance from the lighting object:

    constrain INT_Distance_X to abs( self.Position.X - scene.Background.Sun-thing.Position.X )

    constrain INT_Distance_Y to abs( self.Position.Y - scene.Background.Sun-thing.Position.Y )

    And then we simply do some logic to see if we're too far away from the light (in this instance, minimum distance is 400)

    RULE: if max( self.INT_Distance_X , self.INT_Distance_Y ) < self.INT_Minimum_Illum_Distance {
    Constrain self.alpha to (1-max( self.INT_Distance_Y , self.INT_Distance_X )/ self.INT_Minimum_Illum_Distance )-.2
    }
    else{
    Constrain self.alpha to 0
    }

    That's it!

  • DevirosDeviros Member, PRO Posts: 87

    @uptimistik thank you!

  • SocksSocks London, UK.Member Posts: 12,822
    edited December 2015

    @Deviros said:
    The reason that I'm adding 180 to the angle calculation is to keep the angle above 0 - makes it easier to math.

    You could also use mod to constrain the angle to 0-360 . . . so: X%360

    @Deviros said:> If you didn't have 360 individual lighting images (and you shouldn't, seriously, that would be awful) you would just copy and paste the same image across multiple angles:

    I'd say having 360 individual images, 1 for each angle, is a much more efficient way of doing this, you can lose all the constrains and tables and attributes and simply use a single constrain to constrain the image to the angle between the actor and the light.

    I've done a lot of these dynamic lighting set-ups and after lots and lots of testing having an image for each angle (or for every X degrees) is not only much more efficient but is also much easier to control, adjust and much much simpler to set up.

  • DevirosDeviros Member, PRO Posts: 87

    @Socks Thanks for the feedback on this!

    @Socks said:

    @Deviros said:
    The reason that I'm adding 180 to the angle calculation is to keep the angle above 0 - makes it easier to math.

    You could also use mod to constrain the angle to 0-360 . . . so: X%360

    Good call - that works too.

    @Deviros said:> If you didn't have 360 individual lighting images (and you shouldn't, seriously, that would be awful) you would just copy and paste the same image across multiple angles:

    I'd say having 360 individual images, 1 for each angle, is a much more efficient way of doing this, you can lose all the constrains and tables and attributes and simply use a single constrain to constrain the image to the angle between the actor and the light.

    I've done a lot of these dynamic lighting set-ups and after lots and lots of testing having an image for each angle (or for every X degrees) is not only much more efficient but is also much easier to control, adjust and much much simpler to set up.

    The only problem i'm seeing (and i could be reading your implementation incorrectly) with the 1-1 angle to image constrain method is that that limits you to one actor, with one "master" image (no animation), AND it interferes with custom score image constraints!

    You also end up potentially doubling, tripling, or quadrupling (depending on the number of 'stops' around the angle wheel you're doing) the number of images in your project. It's not necessary to have every angle of the 360 degrees covered by an angle specific lighting image - you can still get smooth lighting animation with every other or every third angle.

    It would also interfere with having other actors with lighting as well!

  • pHghostpHghost London, UKMember Posts: 2,342

    @Deviros said:
    If you didn't have 360 individual lighting images (and you shouldn't, seriously, that would be awful) you would just copy and paste the same image across multiple angles:

    @Socks said:
    I'd say having 360 individual images, 1 for each angle, is a much more efficient way of doing this, you can lose all the constrains and tables and attributes and simply use a single constrain to constrain the image to the angle between the actor and the light.

    I've done a lot of these dynamic lighting set-ups and after lots and lots of testing having an image for each angle (or for every X degrees) is not only much more efficient but is also much easier to control, adjust and much much simpler to set up.

    Entirely agree with @Socks here. In terms of effect on the speed of the game etc. 360 individual images is a much more elegant and straightforward solution. You can even reduce the number if you don't need as precise or granular light control. One image per 2-3 degrees can be enough in many situations. Also, you can reduce the amount of images if you have symmetrical actors (as mentioned by @Socks in one previous thread).

  • DevirosDeviros Member, PRO Posts: 87

    @pHghost maybe I'm not grasping something here, but if I have an actor, with three animation states, and I want each state to be able to have the lighting applied, how can I do a constrain to (INT_Angle).png and still be able to maintain animations?

    Further, how could I light many actors, if they are all different shapes?

    Finally, would adding the bulk of twice as many (or more) images to the application not cause size and memory usage concerns?

  • SocksSocks London, UK.Member Posts: 12,822

    @Deviros said:
    The only problem i'm seeing (and i could be reading your implementation incorrectly) with the 1-1 angle to image constrain method is that that limits you to one actor, with one "master" image (no animation)

    You can juggle the maths to allow animation, it's pretty straightforward too.

    @Deviros said:
    AND it interferes with custom score image constraints!

    Not sure what that means.

    @Deviros said:
    You also end up potentially doubling, tripling, or quadrupling (depending on the number of 'stops' around the angle wheel you're doing) the number of images in your project.

    Yep ! You end up with a lot of images, GameSalad is enormously more efficient when all it needs to do is to juggle images, compared to when it has to deal with lots of constrains/tables/rules (and so on).

    Image these two scenarios . . .

    1) An actor that has a couple of constrains - and accesses various images (just one at a time) from a bank of 999 images.

    2) An actor that has 7 or 8 constrains - and uses just a few images (at the same time).

    . . . I think most people's initial thought is to avoid scenario 1 and go for scenario 2, after all scenario 1 comes with 999 images (!) but scenario 1 will place much less strain on a device's processor.

    @Deviros said:
    It's not necessary to have every angle of the 360 degrees covered by an angle specific lighting image - you can still get smooth lighting animation with every other or every third angle.

    Agreed, it's not always necessary, but it really depends on your particular project, if - for example - you have an asteroid that is spinning and moving, and you want it to be lit from one side, then you could probably get away with having an image for every 5° or 10° increment (depending on its speed), but for other situations covering every 1° (or even less) really does make a difference.

    Also whether you have an image for every 1° or every 5° makes no difference to the strain placed on the device's processor - for example if we were constraining an actors image to its rotation then on each code cycle GS will get to our actor and check which image is needed for display, whether the image needed is 'Asteroid_004' or 'Asteroid17' makes no difference, it's only every using 1 image.

    @Deviros said
    It would also interfere with having other actors with lighting as well!

    I'm also not sure what this means ?

  • SocksSocks London, UK.Member Posts: 12,822

    @pHghost said:
    In terms of effect on the speed of the game etc. 360 individual images is a much more elegant and straightforward solution.

    It's funny, if you've ever spent time exploring the resources / assets of commercial software like Logic Pro and Photoshop and so on, this is exactly what you find, for example if there is a knob in Logic Pro (like a pan control or EQ knob) you will find the resource for it is a strip of images, incrementing though all the values, an image for every position - rather than a single image that is rotated at run time.

    @pHghost said:
    You can even reduce the number if you don't need as precise or granular light control. One image per 2-3 degrees can be enough in many situations.

    I mentioned this above, but it's worth pointing out that the precision (the number of images) has no effect on processor strain (with a few caveats), I'm not saying this is what you are saying, and I agree that there are situations where you really don't need so many images, but I suspect it's tempting for people to fall into the trap of thinking a 20 frame animation is less CPU intensive than a 40 frame animation of the same length (smoother motion) or having 90 images for a dynamically lit object rather than 360.

    @pHghost said:
    Also, you can reduce the amount of images if you have symmetrical actors (as mentioned by @Socks in one previous thread).

    Yeah, for example a cube would only need to resolve a 90° turn.

  • DevirosDeviros Member, PRO Posts: 87
    edited December 2015

    @Socks

    Ok! I think I see where my confusion is here. The method I'm outlining here allows you to have

    A) multiple light sources
    B) moving light sources
    C) animation and dynamic lighting across multiple actors that all follows the same rules with a table that is easily accessible and editable for all applicable actors.

    This can dramatically speed up development as you don't have to render every combination of actor + lighting angle - you only have to render a maximum of 360 lighting angles and one actor, especially with an actor like a box that's rotating.

  • SocksSocks London, UK.Member Posts: 12,822

    @Deviros said:
    @Socks

    Ok! I think I see where my confusion is here. The method I'm outlining here allows you to have

    A) multiple light sources
    B) moving light sources
    C) animation and dynamic lighting across multiple actors that all follows the same rules with a table that is easily accessible and editable for all applicable actors.

    Yes, you can do this with an image based approach, hold on there is an old thread dealing with this - with videos too (if they are still working) - I'll see if I can find it . . .

    @Deviros said:
    This can dramatically speed up development as you don't have to render every combination of actor + lighting angle - you only have to render a maximum of 360 lighting angles and one actor, especially with an actor like a box that's rotating.

    The image based approach really is much more straightforward, with far simpler rules !

  • SocksSocks London, UK.Member Posts: 12,822

    @Socks said:
    Yes, you can do this with an image based approach, hold on there is an old thread dealing with this - with videos too (if they are still working) - I'll see if I can find it . . .

    I can never find a thread when I need it, it's probably long sunk into the dark history of the forums, but I have dug out one of the project files, I'll make a quick video for you . . .

  • SocksSocks London, UK.Member Posts: 12,822
    edited December 2015

    Here's an old dynamic lighting experiment:

    And here are some more recent ones:

  • RainbrosRainbros Member Posts: 124

    @Socks While the image method may be more processor-efficient, doesn't rendering and exporting 360 or so separate images take a ton of time? How would you go about doing this in, say, Illustrator? Especially if you want to do this for multiple actors/animations...

  • SocksSocks London, UK.Member Posts: 12,822
    edited December 2015

    @Rainbros said:
    @Socks While the image method may be more processor-efficient, doesn't rendering and exporting 360 or so separate images take a ton of time?

    The 360 rock angles/images in the above example take around 35 seconds to render, so around a tenth of a second for each image (and this is on a quite old iMac), but of course this all would depend on numerous factors, the software you use, the style you are working in, the size/resolution, the complexity of your lighting model, your own skills . . . . and so on . . . for example some skilled 8bit illustrator could probably knock out 100 sequential images in an hour (from a base template) where it might take me all day (and mine would look crap :smile: ).

    So there is no set or fixed amount of time the creation of your images will take, somethings can be done in minutes, other more ambitious things might take days.

    @Rainbros said:
    How would you go about doing this in, say, Illustrator? Especially if you want to do this for multiple actors/animations...

    Like I say to above, without context it's an impossible question to answer, without knowing the style you work in, the complexity of your images, the interaction with the lighting or even the style of the lighting (a hot spot, a broad specular highlight, smile diffuse shadowing / shading . . . etc) ?

  • pHghostpHghost London, UKMember Posts: 2,342

    @Socks said:
    I mentioned this above, but it's worth pointing out that the precision (the number of images) has no effect on processor strain (with a few caveats), I'm not saying this is what you are saying, and I agree that there are situations where you really don't need so many images, but I suspect it's tempting for people to fall into the trap of thinking a 20 frame animation is less CPU intensive than a 40 frame animation of the same length (smoother motion) or having 90 images for a dynamically lit object rather than 360.

    Absolutely, the effect on the CPU between the two should be nearing 0.

    In some cases less images could help keep the size of the app down. Especially if you have lots of different actors and you need to publish on Android (I hear they still have low filesize limits).

  • DevirosDeviros Member, PRO Posts: 87

    @Socks Those are really quite cool - thanks for sharing that.

    Upon rereading what you wrote (not on my phone, i might add) it's more clear to me where i started to misunderstand - and how far off track i got - how you get the images to the final display - constrained from a table, or via the name - doesn't really change the tables i was really thinking about (yeah, i know - communication issues)

    I was really thinking of the light positions and having THEM in a table so you could do something like this:

    So - yea - the method of getting the images themselves is rather inconsequential in this case.

  • DevirosDeviros Member, PRO Posts: 87

    And again - but with distance lighting applied.

  • SocksSocks London, UK.Member Posts: 12,822

    @Deviros said:
    @Socks Those are really quite cool - thanks for sharing that.

    They are basically using exactly the same approach you are using, just pre-rendering the result rather than calculating it at run time.

    @Deviros said:
    So - yea - the method of getting the images themselves is rather inconsequential in this case.

    Agreed, whether through tables or constraints or animation or something else, it doesn't much matter, the distinction here is pre-rendering vs calculating during run time, I imagine there are situations where either one might offer an advantage, but for general tasks (example: a spinning asteroid or bouncy ball reflecting its environment) I've found that the pre-rendered route is pretty much always more efficient, smoother, less straining on the device's CPU (GS excels at throwing around images) . . . and I can absolutely see why we tend to shy away from having - for example - 200 images where we could otherwise have 5 or 6 images, my own instinct is '200 images bad ! 6 images good', whereas in reality the 200 image solution is often smoother, less CPU intensive and simpler to set up and work with.

  • pHghostpHghost London, UKMember Posts: 2,342

    @Deviros

    I think that if you have a game that relies only on square and round shapes and you only need rim lights, your method will work well as a mass-scale deployment (albeit with a draw on the CPU).

    The benefit of the 360 image method (apart from lower CPU draw, which depending on the complexity of your game can be a non-issue) is that you can have much hugely varied geometry (especially with custom collision shapes now) and intricate light play.

  • rainwaterstudiosrainwaterstudios Member Posts: 198

    @Socks said:
    Here's an old dynamic lighting experiment:

    And here are some more recent ones:

    Do you still have the project files for these?

  • 3xL3xL Member Posts: 676

    For a static area like the lava, wouldn't it be easier to put an overlaid read haze on layer one? With additive blend? Maybe I'm explaining it wrong but I've done something similar to this on my old game.

Sign In or Register to comment.