Preventing Shadows from Incorrectly Casting Through Floors

I’m facing a shadow rendering issue in Three.js. I have a three-floor building model, and on the third floor, there’s a car. I’m using a directional light to cast shadows. The setup is such that the car casts shadows (castShadow=true, receiveShadow=false), and the floors receive them (castShadow=false, receiveShadow=true). However, the problem arises with the shadow casting behavior. Instead of being limited to the third floor, where the car is located, the shadow also incorrectly appears on the first and second floors. This seems like a shadow leakage issue where the shadow penetrates through these floors.

How can I prevent the shadow from incorrectly casting onto the wrong floors, ensuring it only appears on the third floor directly under the car? Any advice or solutions to fix this shadow problem would be greatly appreciated.

You’d need to enable shadow casting on the floor as well - when ‘castShadow’ is set of false on the floor, it becomes invisible to the shadow camera, therefore only the shadow of the car is rendered and applied to all objects in the scene (resulting in car shadow being visible on the lower floors.)

Thank you for your timely reply. Your suggestion works well in conventional scenarios. However, my project has very specific requirements. It’s similar to a CAD application, so the graphics need to be clean and simple. The lighting should be evenly applied to ensure everything is clearly visible. In this context, shadows are used only for slight and subtle visual enhancement. Therefore, the rendering in my project does not need to be as realistic as in video games, for example.

If I set the floor to cast shadows, the underlying floors become dark, which isn’t suitable for my CAD-like application. The shadow on the floor becomes too prominent:

I understand my needs might be somewhat unique, but I would greatly appreciate any guidance:

  • Should I tweak the scene setup and rendering process to control shadow casting/receiving within a specific scope (like a specific floor)?
  • Could layers be utilized for this purpose? I’m aware that we can have a maximum of 32 layers, but my use case might involve more than that number of floors.
  • Or, should I dive into shader programming to implement my own logic for rendering the desired shadows?

That’s not how shadow map works. There’s no “scope” - shadow camera looks in a specific direction and renders things that it sees as light obstructions.

If clarity and contrast is what you’re looking for - I’d take a look at N8AO or any other ambient occlusion postprocessing. N8AO can create faux shadows quite well, and applies them only to objects that are close to one another, regardless if it’s tiny objects or cars. Properly configured, it can create a soft shade between the car and the floor, and leave the floors underneath untouched.

Layers are a only visibility switches - they don’t affect the final “logic” of rendering the scene, ie. even if a light / shadow source is part of a layer, it’ll still affect the entire scene and all other layers.

If you’d decide to go that way, I’d first try to define the logic behind what you’re trying to achieve - esp. in more complex scenarios.

2 Likes

If the floor is always flat and if the shadow is projected only on the floor, you can mimic the shadow:

  • by preparing the shadow as a texture and apply it to a rectangle below the car
  • by making a gray flat clone of the car and put it below the car

@mjurczyk Thank you very much for the suggestions, which is informative and helpful. I will go AO for now and in future if still needed I can do some research on the shader way.