Jump to content

Shadow quality automatically decreasing


kurhlaa
 Share

Recommended Posts

Hello,

I've created a standard shadowGenerator with var shadowGenerator = new BABYLON.ShadowGenerator(512, light) - after pushing in it multiple objects I've noticed automatic quality decreasing, like that number 512 becomes lower and lower.

For example 1 box: https://www.babylonjs-playground.com/#8NWA0U

The same with only 100 boxes: https://www.babylonjs-playground.com/#8NWA0U#1

 

You see the difference. Testing shows 512 becomes ~24 -> 20 times less.

Is that true that there is a fixed count of "rays" for calculating shadows? Because the more objects I have - the less "rays" gets everyone of them. Of course I could set 4096 instead of 512 - but that dramatically decreases FPS.

 

The main question is how can we get more or less good shadows with big amount of objects? Troubleshooting from https://doc.babylonjs.com/babylon101/shadows doesn't help with that.

Link to comment
Share on other sites

This is normal behavior. Shadow maps have a limited resolution, and as you add objects to your ShadowGenerator at greater distances, the amount of ground the shadow map has to cover expands, therefore becoming more pixelated as it scales up. So, it's really not about the number of objects you add to the ShadowGenerator, but how far apart they are. You'd see the same effect with 2 boxes; one at x:0, z:0 and another at x:100, z:100

There are a couple of ways you can deal with this.

  • In my game, I use as small a shadow map as possible and keep the light that is casting it near the camera (so the shadow map stays centered on the player), but I have the shadow fade toward the edges of the shadow map, so that the shadows don't just disappear suddenly.
  • You can have multiple, small shadow maps; one for each object that requires a high-quality shadow.

 

Link to comment
Share on other sites

@FunFetched, Thanks, limited resolution explains my PG examples.

If I have, for example, a game's scene with size 500x500 or 1000x1000 units - I should create like 10 shadowGenerators for different locations to keep shadows normal?

About the performance - is 1 shadowGenerator with 100 pushed objects the same as 10 shadowGenerators with 10 pushed objects?

Link to comment
Share on other sites

54 minutes ago, Deltakosh said:

Nope they are not the same. I suggest keeping only one shadowGenerator and playing with shadow casters dynamically

Can you show a basic example how would you do that? It's something like "show shadows for the nearest objects only" ?

Link to comment
Share on other sites

2 hours ago, FunFetched said:

In my game, I use as small a shadow map as possible and keep the light that is casting it near the camera (so the shadow map stays centered on the player), but I have the shadow fade toward the edges of the shadow map, so that the shadows don't just disappear suddenly.

Can you create a simple PG example of this? From words I don't understand how does it work and looks like :)

Link to comment
Share on other sites

@FunFetched  I have struggled with this issue too . I would love to hear more about your techniques.

@Deltakosh  if an object is in the renderlist but is not in the camera view does it still take up shadowmap resources?. Also is there anyway to "bake" shadows?. If i know that my light  and object position isn't going to change is it possible to "freeze" the shadow, prevent it from being recomputed every frame?

Link to comment
Share on other sites

@kurhlaa please try to experiment in the playground and I will help if required :) (just add / remove objects from shadowGenerator.renderList)

@satguru The shadowMap only relies on renderlist (as this is a different point of view from the camera which means that even if the camera does not see the object it can still see the shadow). Shadow generators can be frozen with generator.getShadowMap().refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE

 

Link to comment
Share on other sites

@Deltakosh

1) So a quick optimization would be to remove all those meshes which are not being viewed by camera from the shadowmap. Is there quick way to find if a mesh is in the camera view?

2)how do I create mutiple shadowmaps? I created two shadow generator for the same light but only the last one seems to be effective.

3) I see a class called ShadowLight. What is this?

Link to comment
Share on other sites

17 hours ago, Deltakosh said:

Shadow generators can be frozen with generator.getShadowMap().refreshRate = BABYLON.RenderTargetTexture.REFRESHRATE_RENDER_ONCE

I love optimizations when an infinite loop can be replaced with only 1 action.

I tied it - https://www.babylonjs-playground.com/#8NWA0U#3 - I add 1 box, then add 100 boxes, push them to the shadowGenerator, then remove 100 boxes, then move the last one. Result means shadow is still being recomputed - quality is good again and position is changing. In local project with a shadowmap's resolution ~8000 FPS is much lower.

Can we completely freeze the shadows? I mean do the calculations only once in the beginning - draw the shadows where they are, and forget about them. Then there would be no need to hide shadows for invisible or too far objects, useful for static worlds

Link to comment
Share on other sites

@kurhlaa this is exactly what happen in your PG. The shadow is computed once and for all and this is why it is wrong when you move the box as the shadow map is no more updated

@satguru

1. You can use mesh.isInFrustum(BABYLON.Frustum.GetPlanes(camera.getTranformationMatrix()))

2. Light can only have one shaddowGenerator. You may want to use 2 identical lights and switch them on and off

3. It is the minimal interface that all lights have to implement to cast shadow (mostly an internal class)

Link to comment
Share on other sites

@Deltakosh ,

Thanks. That helps a lot.

Ran into another issue. This has to do with  includedOnlyMeshes and shadows.

I thought - lets create two lights and two shadowmaps.
One light and it's shadow map for all static meshes  and the second light and it's shadowmap for just the dynamic mesh.
The first one  is rendered only once and the second one every frame

So I took @kurhlaa

example and modified it as follows

1) added another light - light2

2) created two shadowgenerators, one for each light

3) Added all mesh except the last one to the first shadow generator and the last one to the second shadowgenerator

4) added last box to light2's includedOnlyMeshes

problem - last box does not cast any shadow!!

see

https://www.babylonjs-playground.com/#8NWA0U#5

 

 

Link to comment
Share on other sites

@Deltakosh  Ahh.. didn't realize I had to add ground too.

BUT :) still see an issue  Even though other boxes are not added to "light2" their shadow is still effected by it. If  I change the intensity of "light2" the shadows of all boxes changes. How come?

see line 19 and 20 in

https://www.babylonjs-playground.com/#8NWA0U#7

 

Link to comment
Share on other sites

Boxes are not affected by light2 but ground yes. So you will see that even if boxes cast shadows on the ground for light1, light2 will still contribute to it

The ground color is computed by adding light energy from both lights so even if one light cast shadow, it will still receive light from other light

Link to comment
Share on other sites

14 hours ago, Deltakosh said:

this is exactly what happen in your PG. The shadow is computed once and for all and this is why it is wrong when you move the box as the shadow map is no more updated

Thanks! I didn't noticed that "first calculation" in my PG happens already after I delete 100 boxes, that's why shadow's resolution was good again. I added a 5 sec delay, then removed 100 boxes - resolution stays pixelated now, as expected.

But freezed shadow's position and size is still being recalculated, correct? Because PG examples actually show that :) Can this be excluded from calculations too (so even shadowmap's resolution 10000+ doesn't decrease FPS)?

Link to comment
Share on other sites

23 hours ago, Deltakosh said:

Boxes are not affected by light2 but ground yes. So you will see that even if boxes cast shadows on the ground for light1, light2 will still contribute to it

The ground color is computed by adding light energy from both lights so even if one light cast shadow, it will still receive light from other light

Yes , makes perfect sense.
Lots of good information here.
I need some clarification on includedOnlyMeshes and shadows, but let me open a new topic for that. Do not want to hijack @kurhlaa 's topic  :)

 

 

Link to comment
Share on other sites

16 hours ago, Deltakosh said:

You can ask the light to not recompute position with light.autoUpdateExtends = false

Thanks! These 2 flags greatly improve performance!

You definitely need a check-list somewhere in docs/optimization manuals with such common flags :) so users can enable/disable what they need or don't

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...