How to cast shadows of instances with level of detail?

Hi,
as the title says, I am struggling to cast shadow of instances having level of detail. I am working with Cascaded Shadow Generator, but that should not be the issue.

Only the first LOD seems to cast a shadow, when I add the instance to Shadow Generator

shadowGenerator.addShadowCaster(instance, true)

For the original mesh, I could get the LOD levels and add them to the shadow caster, but they would not show up for the instances of it.

for(const lodLevel oflod.mesh.getLODLevels()){
    shadowGenerator.addShadowCaster(lodLevel.mesh, true)
}

GetLodLevels for instances however is not available, so I could not add it to the shadow caster. There is only the function GetLOD which seems to take it from the original mesh.

Any ideas?

Adapted some playground example, see line 51, 53, 66. Circles do not cast shadows
https://www.babylonjs-playground.com/#RLQ5JX#4

You should set the receiveShadows property of shape2 to true:

https://www.babylonjs-playground.com/#RLQ5JX#5

:smiley: great answer! This is actually true for the ShadowGenerator. I forgot to set CascadedShadowGenerator though. Now its not working anymore: https://www.babylonjs-playground.com/#RLQ5JX#6 :confused:

CSM only works with a directional light.

Thanks a lot! Sorry, my playground did not fully fit the case that I currently experience. Even after setting direcitonal light it seems to work… Now I am not sure why it is not working in my project.
Here is the working playground:
https://www.babylonjs-playground.com/#RLQ5JX#7

Just for completeness:

In my case I disabled the LOD_0 mesh instead of just making it invisible.

lod1.parent = lod0
lod0.addLODLevel(50, lod1)

//the original object should not be visible
//my approach was wrong
lod0.setEnabled(false)
//this is the correct way, as stated in documentation
lod0.isVisible = false

//afterwards instancing with shadows should work properly
instance = lod0.createInstance("")

Hi,
I have to reopen this one. Have a look at this playground:
https://playground.babylonjs.com/#0K8EYN#181

Check the draw calls. The more cylinder (LOD) you see, the higher the draw calls. But if you assign a shadowcaster to it (uncomment the marked line), then the draw calls are really low and everything works fine.

So for instances with LOD to cast shadows in a draw call, one needs to set shadowcaster to each LOD object as well as the instance itself.

Wouldnt it be great to avoid shadow casting for objects that are within a certain distance to the camera while keeping the number of draw calls? So LOD 1 casts shadow and LOD 2 not?

Best,
Martin

Edit: Another observation: By setting box.isVisible=false; the shadow of the cylinder is staying on the ground. However the cylinder cannot be set invisible, since it would increase draw calls, too.

Currently having a look at this.

This PR will fix the problems:

PG: https://playground.babylonjs.com/#F7KZ7C#1

You will be able to use shadows for any lod level you want and you will have the right number of draw calls.

Minor caveat: you should disable the master mesh (see PG above) because I didn’t find a way to make its shadows work in all cases… Namely, you can keep the master mesh enabled if all the lods don’t generate shadows, but if at least one lod is a shadow generator you should disable it.

1 Like

Wow nice! Thanks a lot!

I guess my earlier post, where I was just changing visibility of the master mesh is invalid in this case. So disabling should be the right way now. Looking forward to try it!
(How to cast shadows of instances with level of detail? - Questions - Babylon.js)

@Evgeni_Popov sorry to disturb you again…

I might have found another issue with CascadedShadowMaps and LOD and Instances… I am currently on beta18. Everytime I think I got it, there seem to be some issues appearing, slowing down my game. I pinned it down to the following issue:

In this PG: https://playground.babylonjs.com/#F7KZ7C#2
Draw Calls are low when autoCalcDepthBounds is set to false, but high, when set to true

Hope this is an easy one…

Indeed it is an easy one: it is expected :slight_smile:

autoCalcDepthBounds is a compute intensive setting because it must render the scene with the depth renderer then apply a min/max reduction to compute the min and max depth values.

Having said that, the number of draw calls should also be able to be lowered for the depth renderer as it has been lowered for the shadow generator, will have a look at it.

Nice! Would you be so kind and send a link to the commit? Would like to study the code and try to understand it :slight_smile:

PR is there:

With the PR, you have 22 draw calls intead of 46. Among those 22, 12 are for the depth min/max reducer, so:

  • 3 draw calls for the depth renderer (ground + boxes with lod0 + boxes with lod1)
  • 2 * 2 draw calls for the CSM with 2 cascades (one draw call for boxes with lod0 and another for boxes with lod1 - the ground is not rendered in the shadow maps)
  • 3 draw calls for the actual scene (ground + boxes with lod0 + boxes with lod1)
  • 12 draw calls for the depth min/max reducer
1 Like

Thanks a lot! Will battle test it, when its in the new beta!

Actually, I can increase the draw call from 46 to 80, if I rotate the camera a bit to the right. So in that consequence you could probably advertise this PR with improvment of not only 2x, but even 4x or depending on the setup 1000x… :wink:

I made a new PR to clean everything up, as with my previous PRs I have broken some other things…

Note that with that PR you will need to use the customAllowRendering property to enable/disable shadow casting for the different levels, and you don’t need to add the cylinder/sphere in the shadow generator render list. Also, no more specific case for the master box mesh, you can keep the box enabled, no need to disable it (however, if you want shadows for it, you will of course need to add it to the shadow generator render list):

https://playground.babylonjs.com/#F7KZ7C#9

(will only work as expected once the PR is merged)

Hi,
great to hear, that it is implemented on a lower level. I guess with RTT its more robust. Will test a bit as soon as it is part of playground.

I guess it would be good to see how the documentation needs to be changed, since there are cases when to use object.isVisible, object.setEnabled and shadowGenerator.customAllowRendering There are multiple cases that I came across, that should be probably tested. Hope I dont miss one:

  • LOD with Shadow Generator
  • LOD with Cascaded Shadow Generator
  • LOD with partial shadow casting for i.e. only LOD 1 but not 2
  • all three cases with instances
  • all three cases with instances and the main object invisible

Hopefully everything will work as expected with the PR so you will simply have to setup things as you expect it should work. The only specific thing is to use customAllowRendering to disable shadow casting for some LOD levels if you don’t want all levels to cast shadows.