Problem with shadows/light leaking

Hi all. I’m trying to get shadows working right. But I’m havnig some issues. This screenshot shows the problem:

So in the big hall on the right there is a bright spotlight. You can see that it’s causing a shadow (below the table). The corridor on the left should be totally dark. Nevertheless some light seems to be bleeding over into that corridor. Is there anyway to avoid this and have more accurate shadows?

I use singlepass light rendering:

    renderManager.preferredLightMode = TechniqueDef.LightMode.SinglePass
    renderManager.singlePassLightBatchSize = 6

My shadows are using SpotLightShadowFilter(app.assetManager, 1024). Let me know if you need any other information.


I suspect if you turned off shadows, the hall would still be lit because it’s affected by the light in the room.

So I think it’s not a shadow issue but a lighting issue. The light is too far up the scene graph.

1 Like

Well yes, without shadows the corridor would be lit. That’s to be expected. But why isn’t the big wall between the light and the corridor blocking the light? i.e. why isn’t it casting a shadow? Also what to you mean by the light is too far up the scene graph?

Edit: the light in the hall (on the right) is ok for me. That’s what I want. I’m concerned about the light in the corridor on the left. That corridor should be pitch black because there is a big wall between the light in the hall and that corridor

That is the lighting happening in the shader, and the shader doesn’t know anything about the wall in between, it really only knows if a vertex is facing towards or away from a light, and the distance from the light.

To expand on the last answer

You would need to have a separate node for the room on the left and the room on the right. Then you can attach your light to the right node so it is only affecting the spatial’s attached to that node.

To do something like this without separating the rooms into different nodes would require ray-tracing based shaders I think, which I don’t know much about aside from the fact that they’re very intensive and are still rarely used even in big game studios, likely because they can entirely wreck the frame-rate on anything but the best GPUs, and lots of players will choose higher FPS over better graphics especially in competitive games.

So the solution for graphical/lighting problems like this is usually to trick the user into thinking that the results are realistic by doing something else that requires less resources, in this case it is thankfully as simple as using different nodes for different rooms.

Hmm ok. I would have expected normal shadow casting to solve this. After all, isn’t that what shadow casting is supposed to do? Let the big wall cast a shadow that comes from the light. And that shadow should cover the corridor. I guess I still don’t get why it isn’t working

That is what shadow-casting attempts to do as best as possible, but since it is a post-processing based effect, it is limited in its capabilities. So its great for simulating dynamic shadows, but not for calculating accurate lighting. And I think that if one were to make it work more accurately, the framerate would drastically decrease because shadows are already resource heavy.

I’m no expert in shadow code, but shadow processors really only put a dark texture over top of certain spots after all of the other lighting has happened in the shader. But the shader lighting is what’s responsible for the light becoming dimmer as you get further away from the center of the light.

It all goes back to the fact that simulating lighting 1:1 as it exists in the real world would be impossible or extremely resource heavy, so game devs (especially on the graphics side) have to come up with creative ways to simulate the results of the real world as best as possible, even if it sometimes results in more work just to simulate something that seems so simple in the real world.

1 Like

Ok I see now. Thanks for the explanation. I’ll see if I can come up with workarounds here

1 Like

So just in case: one possible (and probably the best) workaround here was already mentioned: make the two rooms to be parented under separate nodes, and make the light on the right only light up the hierarchy of the corresponding node.

1 Like

While that is a workable solution in some cases it has the unfortunate side effect that the light will not shine through the door

Unfortunately yes… it has to be faked separately then. What you are picturing is realistic light behavior. In games light does not propagate realistically so it doesn’t really “shine through the door”. It’s just that when using shadows the walls would draw some darkness over the floor but it’s not the same as “not drawing light there at all so it’s pitch-black”, it’s more like “drawing light there and then drawing some gray darkness over it”.

In static scenes it’s possible to get something like that, more or less naturally-looking by baking the lightmaps… but that would not work well for a dynamic scene.

Most games where you see light shining through a door dynamically are satisfied with the shadows of the doors working for that. In your case, however, the degree of darkness on the left is probably not the degree of darkness you expect from a shadow of an object. So you can’t use object shadows for that because they are gray and not pitch-black, and you can’t make object shadows pitch-black because it would ruin all other cases.

You could still trick the player into thinking there is light shining through doors if you give the player a lantern/flashlight that is constantly lighting and casting shadows with everything from their perspective. Not a perfect solution, but it would effectively prevent them from noticing that other lights are not lighting up doorway shadows because their own light would be the focus point.

Another tactic is to avoid placing lights near doors, and if you do, then also do your best to light up the room on the other side of the door in a way that makes the lighting discrepancies less noticeable.

You can also consider detaching problematic lights in other rooms when the player isn’t in that room, since they wouldn’t be in there to realize it anyways.

Indoor lighting is definitely a tricky scenario, so I’d probably use a combination of as many of these things as I could to make the best of it.

1 Like

As others have mentioned already the brightness of the floor behind the wall comes from the shading which doesn’t consider the wall at all.

What you could try is to use shadowFilter.setShadowIntensity( 1.0f ) which should turn the transparent shadows into pitch black areas. Those should then completly cover the shaded floor. Of course the drawback would be that all shadows would be pure black (like below the table) and that may not be desired visually…

If none of the proposed solutions works for you, consider baking the lighting and shadows into lightmaps. Then you would potentially have complete artistic freedom about how it should look at the cost of it being a static scene.

1 Like

To put it another way, if your shadow intensity was 100%, ie: totally black, it should completely blacken the hallway.

1 Like

Actually I didn’t put it to 1.0f but I was only using 0.5 so increasing it to 0.7 already improves matters considerably. Thanks

Keep in mind, with forward rendering like JME does, shadows are just a trick. (Shadows can be real with deferred rendering which JME does not support ‘out of the box’.)

The scene is rendered with all lights on affecting anything that they are ‘attached to’ in the scene graph.

Then the scene is rendered from the lights point of view to build a depth map of the “things the light can see”.

Then using the color + depth buffer of the scene, this is used to paint ‘shadow intensity’ anywhere that’s not seen by the light.

So it’s not shadow, it’s just gray paint. The outside hall was lit like normal and then painted with gray paint… the same gray paint used to paint under the table. Paint the hall a darker gray and under the table gets a darker gray, etc…