A few questions about shadows

Hi all, my first post, so first a great thanks for this awesome library :+1:

A few questions about shadows:

  1. In the screenshot below, the ball’s shadow is cast both to upper floor and lower floor. How can I prevent this?

  2. Is it possible to use a light only for shadow purposes? i.e. it wont effect the Scene but only used for rendering the shadows.

  3. Is it possible to intervene and modify the Scene when shadow map is rendered? i.e. the Scene rendered to screen and used for rendering the shadow map will be different. For example, I want to move the ball higher when rendering the shadow map, to emphasize its height.

Thanks,
raft

  1. Either by setting .castShadow = true for the upper floor or .receiveShadow = false; for the lower floor (you can also play with shadow camera frustum, but it’ll likely get messy.)
  2. Can you elaborate on the use-case? (Also, probably no - if you set intensity of the light to 0, shadow goes away with it. If what you mean is to access shadowMap texture - you should be able to do that with a custom shader.)
  3. You don’t really need to touch rendering to get that effect. It should be enough to create 2 root Groups on the scene - one that’ll receive shadows on certain objects (ex. ground), and another one (displaced, moved higher etc.) with duplicated geometry of the objects from the first group, that’ll cast shadows but be hidden from rendering at the same time.

thanks for the response :slight_smile:

  1. himm, actually floor one and two are not different objects.
    to be precise: same type of tiles are grouped as an InstancedMesh, so in the screenshot above, there are two InstancedMeshes: one for regular yellowish tiles, and one for the exit tiles. both InstancedMeshes are spanning multiple floors.
    I guess possibly my best option is playing with shadow camera frustum.

  2. well, the purpose of the ball’s shadow is pointing which tile the ball is over. this is especially important when the ball is jumping high (not touching any tile).
    so I want a sharp dark shadow, but I dont need the lighting itself, ambient light is enough for me. any SpotLight or DirectionalLight will make that part of the scene different from the rest.

  3. I’m not sure I understood this one. can you please elaborate?
    how is it possible to use one group to cast shadows and another to render? or use some object for casting shadows but hide it while rendering?
    if possible, this kind of thing can actually be used to achieve the effect at #2. i.e. cast shadows with light, then render without light.

  1. As noble for the GPU calls as it may seem, you are complicating your life by spanning instanced meshes across several floors - and get little in return. One instanced mesh per floor (including all the tiles for only that floor) should be enough, unless you’re planning to have 100+ visible floors on the screen at any single time (instancing limits the amount of GPU calls, so you’ll get one per floor - it doesn’t optimise the scene geometry-wise.)

  2. If you lower intensities for both ambient and directional light you should get to a point when the light on the scene looks the same as if you’d use only the ambient light (also, consider using hemisphere light - it’s still unnatural, but gives a bit more realistic feel than the ambient light.)

  1. In general - yes. In detail - you cannot split three’s rendering process into “before shadow” and “after shadow” (you can technically render shadow map to a separate render target and play with shaders, but it’s still kind of an overkill. :sweat_smile:) Take a look at this example to see exactly what I meant - if you clone geometry (in reasonable amounts), you can use it to create illusion of the original object casting a shadow from a different position.

Edit: Now that I think about it, I wasn’t 100% correct earlier - you can create a scene in which lights don’t affect objects, but still create shadows.

If you use one of PBR Materials (Standard or Physical) and add a HDRI environment to the scene (like in this example), lights won’t affect PBR meshes - but will still create shadows. It’s a bit tricky way to achieve this result, but it is possible.

The parts of InstancedMeshes share the same geometry and material. I guess this also means, they cannot have different textures.

Different tile types has different textures, like in the screenshot below. How can the whole floor can be a single InstancedMesh in this case? I’m missing something I guess :thinking:

Yup, this is exactly what I did after some digging :slight_smile:

But I changed the shadow.camera of DirectionalLight to PerspectiveCamera with a really small FoV (5), seems to work. Is there any possible issues here?

Thanks, I will give it a try :+1:

Ah, I wasn’t aware transparent objects with 0 opacity can still cast shadows :face_with_monocle: Thanks for the sample :slight_smile:

Just assumed it from what you shared earlier, if they do use different materials, you’re correct, you should use separate instanced meshes. My point was to “combine” meshes only from a single floor, and not create instanced meshes out of tiles on separate floors. You’ll then be able to modify floor shadows separately and not touch the frustum of the shadow camera.

Directional light uses OrthographicCamera for shadow, it should be enough to use a PointLight instead. But the effect will probably be the same.

PointLight is 6 time costly regarding shadows to my understanding, possibly no need for it.

Yes, that is the default. Are there any possible issues if I change the default shadow camera to something else? For example to a PerspectiveCamera? Looks like working fine.

Could you share a source of this bold claim :thinking: ? (I’m not saying you’re wrong, I’m curious.)

it is from threejsfundamentals.org:

Since a PointLight shines in all directions the only relevant settings are near and far . Otherwise the PointLight shadow is effectively 6 SpotLight shadows each one pointing to the face of a cube around the light. This means PointLight shadows are much slower since the entire scene must be drawn 6 times, one for each direction.

1 Like

And that seems to be indeed, very correct. :face_with_monocle:

I thought the resolution would be divided by the amount of directions, but it doesn’t seem to work that way.

yea, my understanding is, since it’s not possible to render a shadow map (or anything) with a FoV larger than PI, they just render it into 6 directions separately.

Returning to original question:

That is the default camera. Are there any possible issues if I change the default shadow camera to something else? For example to a PerspectiveCamera ? Looks like working fine.