Light limit in BGE?

I’m doing some testing on producing modular environment assets and I’ve experienced odd behaviour when adding lighting. My scene contains a modular interior lit by both spotlights and point lamps. When I duplicate the mesh/lights to enlarge the space there’s a limit beyond which the scene will no longer show shaded mode in the viewport or the game engine.

I’ll post screenshots and the blend file soon but in the meantime - does anyone know if there are hard limits to lamp numbers in Blender, and especially in the game engine?

According to the documentation in the code, there is a limit of eight lights per layer and 20 maximum layers per scene, so it’s… a lot of lights. If my understanding of forward rendering is correct and the scene needs to be rendered once per light, that also means that performances should degrade linearly with the number of lights in the scene (the same wouldn’t happen with deferred rendering but other issues would be raised).

But there is a limit to added lights in glsl mode, I think 8

In multitexture mode you can have 8 lights, or you can add 8 lights dynamical.

For each light in GLSL the shader code will extended. So the maximum amount of lights depends on how many code your graphic card can handle (memory, shader units). My GeForce GTX 460 can handle 127 point lights with one material.
But you can’t add lights in GLSL mode. Because the shader will not be updated if you add a light. If you want to add lights dynamically you must add the lights that you want to add later in an inactive layer. Ever light that you want to add later you have to put on the inactive layer. You can’t add a light twice.

You need to think of some way to manage lights. No game engine will simultaneously render 50 lights. They’ll use a whole bunch of tricks to make it look like they do though.

I wrote a lighting manager once, that you set the number of lights/shadow lights you want (it libloaded the in), and it will make sure the closest, biggest lights have them. It had a few bugs so I never released it publically. However, I am just about needing said system in my game so I’ll probably dig it up again soon.
(One of the bugs turned out to be in blender 2.71 that I was using at the time. It’s fixed now thankfully)

No Forward Rendering game engine like the BGE at least. But even deferred shading/lighting or per pixel linked list lighting will have trouble with 50+ lights if they all cover most of the screen. So yes, thinking of lighting as a resource to manage is a good approach to go like, sdfgeoff mentions.

Wow - thanks for all the replies. That’s very helpful. I’ll do some experimenting with various methods of dealing with lighting. It seems particularly tricky when dealing with modular meshes too.

Just place lamps all over the place, set energy to 0.

Make a small script:

  • lamp in range of player obj.energy = lamp[‘energy’].
  • lamp[‘energy’] is a property in the lamp itself with the energy value.
  • u can even add distance property to the lamp as well, so u can check its distance.

This way u can place 1000000 of lamps, but u got only 1-8 burning at all times :slight_smile:

Here’s a simple code for getting a few lights to do the work of potentially thousands.


def dynamic_lights(cont):
    own = cont.owner
    scene = own.scene
        
    ### at start up finds your dynamic lights.
    ### you can have as many or as few as you like.    
    if "dynamic_lights" not in own:
        dynamic_lights = [ob for ob in scene.objects if ob.get("dynamic_light")]
        own['dynamic_lights'] = dynamic_lights
    
    ### each ticthe script gets the objects which will act as light proxies            
    hook_list = [ob for ob in scene.objects if ob.get("light_source")]
    
    ### sorts the lights based on distance to own (player is own)
    hooks = sorted(hook_list,key= lambda self,other = own: self.getDistanceTo(other))
    
    number_of_hooks = len(hooks)
    number_of_lights = len(own['dynamic_lights'])
    
    ### for nearest light proxies moves a real light to their position
    for i in range(number_of_lights):
        light = own['dynamic_lights'][i]
        
        if i < number_of_hooks:
            hook = hooks[i]
                        
            light.worldPosition = hook.worldPosition
            
            light.energy = 1.0
        else:
            light.energy = 0.0  
            
    ### you can expand this by keeping properties on the light proxies
    ### such as energy, color, spotsize etc...          
    
    ### then just try 
    ############################
    ### light.energy = hook.get("energy",1.0)
    ############################
    ### if no property is present it will use the default of 1.0

Put this code on the player with an always sensor set to zero pulse and add a couple of lamps to your active scene. Give those lamps the property:

['dynamic_light']

Now put an “Empty” object anywhere you want to be illuminated by a light. This needs the property:

['light_source']

There’s lots of ways to further refine the script, such as culling from the list of hooks any lights which are outside the camera’s view area, or adding properties to the light proxies to control energy and color etc…
This is just the most basic version of the script.

As far as I can tell there is no limit for lights in glsl. Just added 50 to a scene and they all render. But yeah a better system than rendering all those lights simultaneously should be put in place for your game.

Nice work smoking, I wonder however why this is not a resource in C?

Pretty much every project needed light management, I can’t think of a case other then very small scene where you would not need one,

So, just to confirm, as long as the lamp energy is to “0.0”, it does not render at all? Meaning you can have as many light as you want as long as not more than 8 of them have an energy value above “0.0” at once?

If that’s the case, all I have to do is set their energy values depending on where the player is, right?

I’m venturing into setting up some visuals for my little project :slight_smile:

yeah that is interesting, however ,

I think it still computes a light on startup? not sure though.

Yeah, so that would determine whether you have to just mess with their energy values, or actually add/delete them according to player position. Purely because when doing interiors, you will need a few different lights.

A lamp with zero energy is still being used in render calculations. Unfortunately, the way Blender generates shaders by piping functions together does not make it simple to disable parts of the code. This is especially true when you consider the issues involved with branching on the GPU (depending on the branching condition, the GPU might have to take both branches and throw out one result).

That does not mean that some brave soul couldn’t attempt to minimize calculations on zero energy lights, but for a patch to be considered it would have to be a good, clean implementation. The patch would also have to give a demonstrable performance improvement to be worth complicating the shader code. Also, it would be preferable to not take a performance hit when calculating lights with non-zero energy.

So a lamp with 0 energy require exactly the same amount of processing power as a lamp with 1 energy?

Congrats on 2000 posts :stuck_out_tongue:

So a lamp with 0 energy require exactly the same amount of processing power as a lamp with 1 energy?

Yes. It takes the same processing power.


Attachments


Oh wow I was expecting at least some variation, but wow.

Yep, so you have to make the most of the lights you do have. I find that using a lighting manager along with 4 dynamic lights and a static hemi lamp parented to the camera works well for top down or side scrolling games. Any more than that and the others will be unused most of the time but still being a full drain on resources.