Maximum number of lights?
by Doug Hamilton · in Torque X 2D · 07/02/2009 (11:58 pm) · 15 replies
I've been playing around with TXB for a while now, and I was just working on a level that ended up with over 8 SceneObjects that each have a T2DLightComponent on them, and each component has only 1 point light. But, when I run the game, only the last 8 lights I added to the scene actually do anything, the rest of them seem as if they're disabled. I was under the impression that I could use as many T2DLightComponents as I wanted, is this simply not the case? Can I only use 8 lights in any given scene?
About the author
#2
07/03/2009 (10:41 am)
Ah, ok that would make sense. Is there any way around this? Is there a system built in already that would select only the 8 closest lights to the camera, and enable only those?
#3
07/04/2009 (3:50 am)
I think the 8 lights limit is connected to DirectX's Fixed Functions Pipeline. However TX's shader LightingEffect2D.fx has a limit of 8 lights - maybe that it the limitation you see.
#4
If you edit TXCore's SceneGraph.cs and make the BaseSceneGraph's "GetLights()" method virtual, you can override it in T2D's T2DSceneGraph.cs.
Whereas GetLights() was being passed the whole world boundaries (as far as I can tell) to determine which lights should be used, you can override that and make your own bounding box for checking... and create said bounding box using the bounds of the convenient _camera property in T2DSceneGraph.
I just posted something over on Pino's community project to see if this is a solution that people find acceptable enough to possibly add to the community improvements (the problem still exists in 3.1.5, so we could theoretically add it to that as well). I defer to Pino's wisdom on the subject of whether it's commit-worthy... but I know through my own testing that the approach at least appears to work.
07/30/2010 (1:34 am)
I've been looking through the T2D Source, and it looks to me like we could potentially improve how lighting works by making it (exactly as you said Doug) only select the 8 closest lights to the Camera.If you edit TXCore's SceneGraph.cs and make the BaseSceneGraph's "GetLights()" method virtual, you can override it in T2D's T2DSceneGraph.cs.
Whereas GetLights() was being passed the whole world boundaries (as far as I can tell) to determine which lights should be used, you can override that and make your own bounding box for checking... and create said bounding box using the bounds of the convenient _camera property in T2DSceneGraph.
I just posted something over on Pino's community project to see if this is a solution that people find acceptable enough to possibly add to the community improvements (the problem still exists in 3.1.5, so we could theoretically add it to that as well). I defer to Pino's wisdom on the subject of whether it's commit-worthy... but I know through my own testing that the approach at least appears to work.
#5
07/30/2010 (1:47 am)
I like the queue idea for lights thats already in place, I have scenes with more then 8 lights, and the last lights, usually a random effect that I don't care about, don't get shown, which is the way I like it.
#6
Was that a new revision in the community changes?
07/30/2010 (2:03 am)
There's a queue idea in place? Hmm, I'll have to reexamine the code... it looked to me like it was just picking the first 8 lights it found, even if they're way at the start of the level and you're hanging out at the other end of it.Was that a new revision in the community changes?
#7
07/30/2010 (2:48 am)
No what I mean is the first 8 lights you add will be rendered... it works well for my game, because I spawn lights as the player enters area here let me show you...
#8
If it was changed so only lights within the camera view were returned, then any lights setup to illuminate the entire stage, like a Sun light, wouldn't get used.
07/30/2010 (9:29 am)
As far as I can tell from the lighting code, it is the 8 (or whatever you set the max lights to) lights that will affect the object being lit the most. Based on the lights' Constant Attenuation then its Linear Attenuation.If it was changed so only lights within the camera view were returned, then any lights setup to illuminate the entire stage, like a Sun light, wouldn't get used.
#9
07/30/2010 (4:03 pm)
Exactly Alex! I was thinking the same thing, a few light effects would happen, and the sun would turn off, then come back on when the effects disappeared. With the current situation, that would never happen, because the Sun would be there the longest, since it is a constant light for the scene. I think the thing you absolutely want to avoid is having a light be there, and then disappear, then possibly reappear. With the queue, that does not happen, because a light is either in the queue and will be shown, or its not, lights can't leapfrog over other lights to get shown, just based on the fact that they are close to the camera (what if its just a few sparks?). A few sparks which might normally be a cool effect, would be a disaster if it was turning off other lights.
#10
07/30/2010 (10:29 pm)
Wow Will, that looks great! Every time I see something about this game it just looks more and more interesting!
#11
Also, ditto what Ray said on your game looking great so far!
EDIT: Okay, so digging into it more I see what can be done I think... I just made a "CameraAwareLightComponent" which inherits from T2DLightComponent.
It registers with the ProcessList and has an extra property which is basically a quick and dirty "how much % off the screen should the light be before it gets re-added to the light list" property... I suppose with a bit of effort I could calculate the point at which the light is no longer meaningfully effecting objects on screen and use that to determine the size, but just as a quick and dirty solution this should work for now.
When it's detected as being within that buffer of space around the screen's active view, it will be added into the light queue (and the light queue will thusly handle it however it decides to internally). Otherwise, once it leaves those bounds it will unregister its lights from the light queue.
That should provide a best of both worlds... any scene-wide lights can just remain as T2DLightComponents and always be active for the scene. I tried it out just now... and I do think I'm going to have to do a one time calculation to try and more intelligently figure out when the light doesn't meaningfully effect the scene anymore, but other than that it seems to work.
08/04/2010 (12:06 am)
Ah, honestly I hadn't considered that: that's a good point! So your approach is to put placeholder lights on the map and spawn/despawn them as needed in the scene? It seems like it'd be a good alternative.Also, ditto what Ray said on your game looking great so far!
EDIT: Okay, so digging into it more I see what can be done I think... I just made a "CameraAwareLightComponent" which inherits from T2DLightComponent.
It registers with the ProcessList and has an extra property which is basically a quick and dirty "how much % off the screen should the light be before it gets re-added to the light list" property... I suppose with a bit of effort I could calculate the point at which the light is no longer meaningfully effecting objects on screen and use that to determine the size, but just as a quick and dirty solution this should work for now.
When it's detected as being within that buffer of space around the screen's active view, it will be added into the light queue (and the light queue will thusly handle it however it decides to internally). Otherwise, once it leaves those bounds it will unregister its lights from the light queue.
That should provide a best of both worlds... any scene-wide lights can just remain as T2DLightComponents and always be active for the scene. I tried it out just now... and I do think I'm going to have to do a one time calculation to try and more intelligently figure out when the light doesn't meaningfully effect the scene anymore, but other than that it seems to work.
#12
If you want to disable lights, removing them from the light list, all you have to do set the IsEnabled flag on the light to false and it will remove the light for you, if you set it to true it will add the light to the list again.
But if you do it based solely on the cameras' view you run the risk of lights that should be lighting an object not doing so.
If you want to avoid that you would need to calculate based on what type the light is, Point or Directional and the size of the object. Directional Lights are supposed to light all objects everywhere, so shouldn't really need to be disabled and should be used sparingly. Point lights can be disabled based on the distance from the object to the Point Light and the value of its Linear attenuation.
I've partially done this already. I made modifications to the way lighting works for 2D objects. So, objects that have been rotated and/or flipped receive correct lights. Also, made it so point lights set to layers behind objects don't light them, saving some lighting calculations. I wouldn't mind adding distance based culling of lights, I've already sent the initial set of changes to Pino for possible inclusion into his Repository of Engine changes.
08/04/2010 (6:08 am)
@AlexIf you want to disable lights, removing them from the light list, all you have to do set the IsEnabled flag on the light to false and it will remove the light for you, if you set it to true it will add the light to the list again.
But if you do it based solely on the cameras' view you run the risk of lights that should be lighting an object not doing so.
If you want to avoid that you would need to calculate based on what type the light is, Point or Directional and the size of the object. Directional Lights are supposed to light all objects everywhere, so shouldn't really need to be disabled and should be used sparingly. Point lights can be disabled based on the distance from the object to the Point Light and the value of its Linear attenuation.
I've partially done this already. I made modifications to the way lighting works for 2D objects. So, objects that have been rotated and/or flipped receive correct lights. Also, made it so point lights set to layers behind objects don't light them, saving some lighting calculations. I wouldn't mind adding distance based culling of lights, I've already sent the initial set of changes to Pino for possible inclusion into his Repository of Engine changes.
#13
Aye, I see where you're coming from: that's the one I need to do, is to create the calculation that determines the range at which point lights can be safely disabled. It's that distance based culling that I'm looking to calculate as well: if you've already done it and would be willing to add it to the community project, that would definitely be a free beer for you should we ever meet in person! ;)
The thing that made attenuation seem more complicated to me is that it seems like sometimes linear attenuation doesn't behave in the way I'd expect. For example, in one level there's an extremely bright cyan point light with the same attenuation as other lights (but it has its ambient color set to 7 green and 7 blue respectively) and it doesn't seem to be decreasing in intensity in linear manner anymore. My guess is that the formula gets screwed up if the colors aren't between the values of 0 and 1, but I haven't done enough looking into it to know for sure. All I know at the moment is that the culling calculations I'm making fail in that scenario.
08/06/2010 (1:22 am)
Oh, the Enabled flag! I'm a dummy, d'oh! Somehow amidst all of this I totally forgot about that simple flag. I'll use that in this new component.Aye, I see where you're coming from: that's the one I need to do, is to create the calculation that determines the range at which point lights can be safely disabled. It's that distance based culling that I'm looking to calculate as well: if you've already done it and would be willing to add it to the community project, that would definitely be a free beer for you should we ever meet in person! ;)
The thing that made attenuation seem more complicated to me is that it seems like sometimes linear attenuation doesn't behave in the way I'd expect. For example, in one level there's an extremely bright cyan point light with the same attenuation as other lights (but it has its ambient color set to 7 green and 7 blue respectively) and it doesn't seem to be decreasing in intensity in linear manner anymore. My guess is that the formula gets screwed up if the colors aren't between the values of 0 and 1, but I haven't done enough looking into it to know for sure. All I know at the moment is that the culling calculations I'm making fail in that scenario.
#14
08/06/2010 (1:37 am)
Alex, your summation is correct, the values should be between 0 and 1, and represent a number between 0 and 255.
#15
I don't know if I can post the changes I've made to the TX community project, since it's all mods to the existing classes and shader. But, I'll find out, or if anyone knows feel free to chime in. If it comes to it though, I suppose I can just email you the files I've changed.
08/06/2010 (5:32 am)
@AlexI don't know if I can post the changes I've made to the TX community project, since it's all mods to the existing classes and shader. But, I'll find out, or if anyone knows feel free to chime in. If it comes to it though, I suppose I can just email you the files I've changed.
Torque 3D Owner Gavin Beard
Byte Logic
I do believe that DirectX has a limit of 8 lights, so as TX is built in DirectX it to has this limit.
there is a little info here:
http://www.gamedev.net/community/forums/topic.asp?topic_id=473047