Jump to content

Why the 4 light limit? [EDIT: Limit has been increased!]


Dal
 Share

Recommended Posts

I'm finding I need to have a direction light to light my scene and then a hemispheric light to add more natural ambient lighting. That only leaves 2 lights left for things like torches, which is too limiting for what I'm trying to do.
Are there any plans to increase that limit? This seems to be the biggest limiting factor of the engine for me at the moment. Most other webgl engines seem to have multipass systems that allow a lot more lights in the scene.
For example, here's a nice typescript example of mulitpass lighting in away3d: https://github.com/awayjs/awayjs-examples/blob/master/src/Advanced_MultiPassSponzaDemo.ts

I'm considering digging into the code to try to increase that limit somehow but I wonder if there's a reasoning behind it?

Link to comment
Share on other sites

Hi Dal,

To increase the light limit you will have to change the default shader to support more than 4 lights.

The reason for the 4 lights limit is (mainly) performance. Light calculations are relatively expensive. If you simply add a light, even a small point light with a distance limit, it actually affects all of the meshes' rendering.

You can, however, overwrite those limitations in a different way - each light has a list of meshes it influences OR a list of meshes it should ignore. So if you have a torch on a wall, it should only influence the wall and (maybe) your character. This way you will have better performance and you could define as many lights as you wish.

The lists are called:

light.includedOnlyMeshes AND/OR light.excludedMeshes . Add meshes to those lists to control which meshes the light influences.

Link to comment
Share on other sites

2 hours ago, RaananW said:

Hi Dal,

To increase the light limit you will have to change the default shader to support more than 4 lights.

The reason for the 4 lights limit is (mainly) performance. Light calculations are relatively expensive. If you simply add a light, even a small point light with a distance limit, it actually affects all of the meshes' rendering.

You can, however, overwrite those limitations in a different way - each light has a list of meshes it influences OR a list of meshes it should ignore. So if you have a torch on a wall, it should only influence the wall and (maybe) your character. This way you will have better performance and you could define as many lights as you wish.

The lists are called:

light.includedOnlyMeshes AND/OR light.excludedMeshes . Add meshes to those lists to control which meshes the light influences.

Hey thats cool! I didnt know about that.

That gives me an idea for a script that goes through all meshes in the scene, picks which lights influence it most and "subscribes" itself to those. Could that work? The only issue I can see is what about things like the terrain... the mesh can be very large and, even though we can turn off lights that are far away, with the terrain they might still be very much visible.

How do other engines achieve lots of lights in their forward renderers? From what I've read, deferred lighting would cause a lot headaches with transparency and PBR but could we maybe implement a better multipass approach like Away3d? http://typescript.away3d.com/examples/Advanced_MultiPassSponzaDemo.html
They've already ported it all to Typescript and it's under Apache license too, so perhaps we could use it? https://github.com/awayjs/awayjs-renderergl/blob/master/lib/shaders/LightingShader.ts

Being able to add lots of lights to the scene is really the only weakness I can see in Babylon now vs all the other webgl engines out there... in most other ways it complete dominates :D

p.s. They also have cascading shadows implement which we also need in Babylon https://github.com/awayjs/awayjs-display/blob/master/lib/materials/shadowmappers/CascadeShadowMapper.ts

Link to comment
Share on other sites

I do not know if that works, but remember this question: "Is a mesh really being lit if it cannot be seen in the current frame?" (similar to does a falling tree make a sound if there is no one there to hear it?)

One way to seemingly get more lights than you actually have, is to put a light on the camera.  Call it "just in time lighting".  The customers of your game will neither know nor care, that unseen parts of your scene are being virtual photon starved.  The camera light does not have to be the only light or full strength, but now everything does not have to be lit at all times. 

I would argue if those other webgl games force the simpleton concept that you have to have lights all over the place, they are the weak ones.  In webgl 1.0, the # of vertex uniforms is very limited on mobile platforms.  Lights compete with bones.  Bad things can happen when you run out.

var camera = new BABYLON.FreeCamera(...);
scene.activeCameras.push(camera); 
camera.attachControl(canvas);
        
var light = new BABYLON.PointLight("spot", BABYLON.Vector3.Zero(), scene);
light.intensity = 1;
light.specular = new BABYLON.Color3(.1, .1, .1);
        
scene.beforeCameraRender = function () {
    light.position = camera.position;
};

 

Link to comment
Share on other sites

Can't agree more with JCPalmer. We are under a really limited resources constraint.

Having 4 lights already generate shaders almost not renderable on some devices: http://www.babylonjs.com/Demos/Lights/

 

So the real question is: Do you REALLY need 4 dynamics lights on a specific object? Dynamic means: the light HAS to move. Else you are wasting resources. If lights are not moving, just use a baked texture :)

 

Link to comment
Share on other sites

@JCPalmer @Deltakosh

Perhaps what I am looking for is more like a light manager system in that case...
Maybe when lights or meshes are added/removed/moved in the scene, the LightingManager will evaluate which meshes should be affected by the light. For a pointlight or spotlight we should only get the meshes within a radius. For a moving player character, we should only pick the most important lights rather than an arbitrary first 4 in the scene?).

I've just made a little test in PlayCanvas: https://playcanvas.com/project/395318/

I'm not familiar with their tools so its not very good, but what I am trying to show is that given a large terrain with lots of lights, it would be hard to pick which lights to use... in this playcanvas scene the "terrain" receives more than a dozen different lights - because of its size it comes under the influence of a lot of different lights.
For an outdoor scene, if we assume a directional light for the sun is essential, and then we probably need a hemispherical light to give us some basic global illumination, we only have 2 light slots left on that huge terrain. Sure we can switch them off based on distance but its going to be noticable. 

Also, why not enable the shader to support more lights but have some flags to limit them rather than hard limits? The scene optimizer could limit the lights or enable more as part of the auto-optimization process.

 

 

Link to comment
Share on other sites

Actually... thinking about it, in most cases where I need "dynamic" lights, I don't need them completely dynamic... lightmapping could work, they just need to be updatable.

Perhaps baking the lights to a texture could allow a lot of lights on the terrain but then the map would need to be updated for night/day transitions and when lights are switched on/off and such.
If we had something like we have with the shadow renderer where we can cast shadows but set it to update 0 to render only once....we could render lights to a texture but only update them when something changes.

When the character walks close to a fire, the dynamic light can be enabled and set to affect ONLY the character(s) in range, but when no character is in range the light can be switched off and fall back to the lightmap. Perhaps an octree could be used to pick which lights should be considered by the camera, and then the light manager should check to see which of those lights are within range of a character, and if they are, it enables a dynamic light but ONLY affecting those characters which are in range.

Does that kind of system sound like it might work?

Link to comment
Share on other sites

So it could be cool to have an automatic lightmapper, I agree:) need to add it to our roadmap

But so far, you can already have some kind of light manager: every light has a range. Objects outside the range are automatically removed from light influence list. So you can have dozens of lights. As long as you limit the range, this could work 

Link to comment
Share on other sites

18 hours ago, Dal said:

Perhaps baking the lights to a texture could allow a lot of lights on the terrain but then the map would need to be updated for night/day transitions and when lights are switched on/off and such.

Hi guys.  Sorry to butt-in, but I had to show Dal my stupid streetlight demo:)

Maybe the important thing to note... is that each white circle on the roadway... is a texture on a plane... blended with the roadway material beneath.  Take note that I made this demo LONG before I knew anything about textures, so I just blindly activated everything until it worked.  I'm sure there are many wasted properties set on my "light circle" material.  The main thing is... I got it done.  I faked 15 lights on a single material... and without any baking or lightmap crap.

Let's pretend a hallway in a fancy hotel... gaslights lining the walls... a nice patterned wallpaper.  You could use my "white-out" circle on the walls behind each gaslight.  Then add a single REAL directional light... parented to the player.  Then, as a player passes the gaslight, you light-them up with the directional light that they are actually carrying with them. 

See how my box lights-up as it passes under the street lights?  Pure fake, baby.  The light that lights the box... is carried by the box.

BUT... my roadway is NOT a paisley print wallpaper.  SOME testing would need to happen... to see how well the wallpaper pattern behind the gaslights... would show-through the white circle.  Sure, the white circle over-layed texture could be bright enough to "wash out" the wall paper pattern.  But, in reality, the wall paper pattern SHOULD remain somewhat visible, even with the white circle texture layered atop.  Fine tuning.  :)

I LOVE foolery, don't you?  :)  All in all, I just wanted to give you some other options to think about.  There is another user who is/was grappling-with multi-lights, recently, too.  His forum thread is right here.  Good light discussions went-on in that thread.  Be well!

Link to comment
Share on other sites

Great example!

But you know what? I decided to give more flexibility here !

So please let me introduce with StandardMaterial.maxSimultaneousLights!!!! By default this parameter is 4 to keep everything backward compatible.

But guess what? YOU CAN NOW CHANGE IT:http://www.babylonjs-playground.com/#IRVAX#0 (yeah there is 6 dynamics lights here!)

But you must be warned: with great power comes great responsibility. With more lights, it will be easier to reach mobile devices limitation. Babylon.js will take care of it by deactivating lights but it will do it blindly (ohohoh! blindly with lights)

Link to comment
Share on other sites

Wow!  THANKS DK!  This is great!  And what a fun introduction post!  :D  You are a "nut"!  Well on your way to earning your "Wing".  Congrats on the quality feature-add, and congrats to Dal on the back-alley contribution to BJS.  Well done, guys.

Link to comment
Share on other sites

Wow! Thanks @Deltakosh, this is really useful! So now in theory, if I increase the limit a little, and make all the pointlights have a range the same size as the area they light, then it should allow me to have quite a lot of lights running in the scene? I will have to test this out.
I guess with a large terrain, we really do need to use lightmapping though, since we could have e.g. 20 houses on our terrain and all of them need to cast lights, and they could theoretically all been seen at once as we approach the town, but it will be too expensive to run 20 lights.

As a temporary hack, could the shadowrenderer be inverted somehow? So instead of painting the black region into the shadow map we paint a light area in the lightmap of everything inside a cone and subtract the shadow? That wouldn't take care of bounces and proper falloff and such, but it might be enough to make a spot on the terrain like in Wingnut's demo without having to do it manually?

 

Link to comment
Share on other sites

Hi Dal.  Did you mean to say... "All of the houses need to cast shadows" (not lights)?  One point light sun, 10,000 houses with shadows... no problem.  ;)

Oh wait, do point lights do shadows?  I forget.  I think they do... hot new feature

(see line 41, Dal?  Ya just cram all your buildings into the shadow generator's renderList.  You probably knew all this already, and I have wandered off-topic)

Link to comment
Share on other sites

9 minutes ago, Wingnut said:

Hi Dal.  Did you mean to say... "All of the houses need to cast shadows" (not lights)?  One point light sun, 10,000 houses with shadows... no problem.  ;)

Oh wait, do point lights do shadows?  I forget.  I think they do... hot new feature

(see line 41, Dal?  Ya just cram all your buildings into the shadow generator's renderList.  You probably knew all this already, and I have wandered off-topic)

No, I do mean cast lights... if you think about it, in your streetlight demo, a pointlight really just draws a circle of light onto the ground. Its kind of like casting an anti-shadow :D

 The pointlight shadow mapper works out all the areas that should be dark and draws it to the shadow map. I'm wondering if its code could be hacked so that it just makes everything lighter that is within its radius, EXCEPT the shadow area.

Link to comment
Share on other sites

Oh...  you mean... the houses/buildings cast light through their windows?  ohhh.  Sorry.  Yeah, an inverse shadow map...  interesting.  A pointLight inside the building, shining through a tiled window, would make tile-shaped brighter-spots on the ground outside.  Yeah, that would be... something to behold.  Good idea.  Well, an interesting idea... kind of scary.  heh

Would .shadowColor do it?  I don't think it exists, but maybe.  Or, as you suggested... a lightShadowRendererThingy.  Silhouetter v1.0  :)

"anti-shadow"  haha.  Good comedy, but good description, too.

Link to comment
Share on other sites

13 minutes ago, Wingnut said:

Would .shadowColor do it?  I don't think it exists, but maybe.  Or, as you suggested... a lightShadowRendererThingy.  Silhouetter v1.0  :)

Well, it would have to be a bit smarter than that... shadowColor would just mean our trees will shine a tree-shaped light onto the ground beside them. We need to invert the shape.

The way I would probably attempt it (with no previous knowledge of this kind of thing) is to create a sphere around the light which has its area of effect, then apply light to the lightmaps of all objects that fall inside it, and subtract the shadowmap from it.

Link to comment
Share on other sites

11 hours ago, Deltakosh said:

Babylon.js will take care of it by deactivating lights but it will do it blindly (ohohoh! blindly with lights)

Can you make it switch off lights in order of light type?

If we switch off pointlights first, then hemispheric, then directional I think it would be much better.  Most scenes have a sun directional light and/or hemispheric ambient lighting so those should switch off last. The point lights are used more for light sources that move around in the scene, so those are less important. We should never switch the sun off just because we're too close to a fireplace :D

p.s. Can this also work with the PBRMaterial?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...