Jump to content

Suggestions on shadow optimizations

Go to solution Solved by Deltakosh,

Recommended Posts

I'm currently experimenting with babylon.js and have some questions about optimizing shadows. I'm playing with a large forest scene, with trees and rocks. I'd like the trees to cast shadows on to the rocks and the ground. Here's an example of part of my scene:




It works, but sometimes renders slowly (low FPS). To try to improve the situation, I've added fake (rendered) shadows to the ground texture so I could get away with having fewer trees explicitly cast shadows. I also reduced the resolution of my shadowmap to 512 and use the usePoissonSampling option to try to hide the low resolution a bit. useVarianceShadowMap didn't work for me because it changed the color of the ground even when I when I go outside the forest (no shadows should be cast).


Is there anything more I can do to optimize the performance of these shadows (both casting and receiving)? For example:


1) Is there an option to increase the strength of the Poisson-sampling blur? That way I cold get away with lower-resolution shadowmaps.


2) For static objects (all the objects in my scene), are the shadows calculated once and applied to the ground texture ("baked" onto the texture, in blender parlance), or are they generated de novo for each frame? Is there any way, within babylon.js, to bake the shadows onto the ground texture once so they don't have to be rerendered?


3) Is there a way to restrict cast shadows to a specific area (for example, only within 10 units of the camera)?


4) Is there a way to change the color of the shadow? Right now it's pitch black. It would be nice if you could still see the ground where the shadow is cast, albeit drawn darker.


Thanks for all your help with this. I've really enjoyed using babylon.js so far!

Link to post
Share on other sites
  • Solution

1. Not yet but shader could be easily updated

2. This is your best option: use shadowGenerator.getShadowMap().refreshRate = 0. In this case the shadow map will be computed just once (beware, you have to ensure that all meshes are ready to render before creating the shadow Generator because, you know, it will be rendered just once :))

3. Not directly but you can control the refresh rate again here. You can also control which meshes are inside the shadowMap.renderList

4. Shadows are not drawn actually. They block the lighting. So to see the ground, just add some emissiveColor to the material of the ground




Link to post
Share on other sites

I do not know: shadowGenerator.getShadowMap().refreshRate = 0.


This is for all the subject of the stage, but for objects that this moves (objet animated), how to have a default refleshRate for dynamic object and RefreshRate to 0 for static objects ? This topic interests me greatly.



Link to post
Share on other sites
4. Shadows are not drawn actually. They block the lighting. So to see the ground, just add some emissiveColor to the material of the ground



Wouldn't be interesting to have a shadow power (or intensity) param?

Adding some emissive is not always the right way to go, because that can affect overall rendering aspect when materials and lights are already fine tuned. Other way to change shadow strength is to put some more lights, but for performance reason a strength param could be interesting.

Link to post
Share on other sites

Wonderful solutions all around. Making the ground emissive made the shadows look much more realistic. To improve performance, I ended up having my script check the distances between the camera and all scene objects every 2.5 seconds. I updated shadowGenerator.getShadowMap().renderList periodically to include all the appropriate objects within a given cutoff distance. No need to render the shadows for objects that are far away in my case. I'd like to know how to use octrees to speed up those distance calculations, but I'll post that to another question in a second.


For reasons I don't understand, I can't get a good shadow-casting light position that casts shadows on all the objects of my expansive scene. As a fix, I made the shadow-generating light follow the camera. That works well, but it makes using "shadowGenerator.getShadowMap().refreshRate = 0" a bad idea.  With "shadowGenerator.getShadowMap().refreshRate = 0", the regions of my scene that are initially "shadowless" never get updated with shadows, even if the light continues to follow the camera.



I'd appreciate it if anyone could explain the best way to choose the position of the shadow-casting light so as to maximize the area of the scene that is "shadowed." Thanks. 

Link to post
Share on other sites

If the light is a directional light, you should consider the position as the position of the camera that will render the shadowmap. With babylon.js v2.1, the light can determine automatically the best projection matrix (and you can use the debugLayer to see the content of the shadowMap)


The best position is: close enough to get the best precision

Link to post
Share on other sites

It's helpful to think of the light position as a camera for the shadowmap. Is there a way to increase the "field of view"/"field of vision" of the source, so that it covers a greater area?


I'm happy to share my shadow LOD code if it would be helpful, though I'd guess that you folks are 1000x better at writing optimized code than an amateur like me. :) If you're really ambitious, you could also allow for distance-dependent changes to the shadowmap resolution... 

Link to post
Share on other sites
  • 6 months later...

I have question about shadows too...... I;ve separated static and dynamic objects into two shadowGenerators, (Static & dynamic)  so static shadow refresh rate is 60 and dynamic is 1  ,,,, --- > work pretty good but,,,,, is there way to merge two shadowgenerators shadowmaps into one in output because second shadowgenerator is overlaying first one,,,, and static shadow becomes darker if dynamic shadow overlaps static ..




This effect is not physicaly realistic  in real world.......


it should be


output color  = total diffuse * light


final color = output color  + ((shadowgenerator1 shadow map + shadowgenerator2 shadowmap)*shadow intensity)   



in my opinion shadowmaps should be rgb color (0,0,0) "or whatever color u want" * alpha (shadowintensity)


thanks ..

Link to post
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.

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.

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...