layerMask stopping shadow?

I don’t think they are linked, but would there be any reason why a layerMask on a mesh that hides the mesh from the active camera would also hide it from the CascadeShadowMap?

I thought I was able to set layerMasks and still have them appear on the shadow casting, but for some reason that is currently not working in one of my setups.

this is an exact demo showing whats going on… a box with a layerMask = 0 still shows up on the shadowCast, but the mesh that was imported set to a layerMask = 0 hides it from the shadow cast.

As you explicitly put meshes in the render list of the shadow generator, the system assumes that you will manage the list of shadow casters yourself, so it does not check the layer mask of the meshes against the layer mask of the camera. The layer masks are checked only if you set shadowGenerator.getShadowMap().renderList = null.

If you want to make the shadow disappear when the mesh is not rendered by the camera, you are responsible to remove the mesh from the render list.

Now, on the opposite, if you keep the mesh in the list because you want it to cast a shadow even if not rendered by the camera, it does work as expected (see your cube) EXCEPT for a small detail when your mesh has a skeleton: the skeleton is not initialized properly because the linked mesh has not been rendered a single time, and the initializing function is called when the mesh is rendered (more precisely, it is called when a mesh is deemed to be an “active mesh”, but a mesh not rendered because of incompatible layer mask is not an “active mesh”).

If you set the layer mask of the robot after a timeout of say 500ms, you will see that its shadow is displayed because you let time to the system to run the initializing function of the skeleton.

To do it in a cleaner way, you can call mesh.skeleton.prepare() yourself, which will initialize the skeleton properly. If you want your shadow to follow the animation of the robot, you will need to make the animation run by calling prepare at each frame. The easiest way is to do it in scene.onBeforeRenderObservable: