Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Tighter shadow caster culling #33340

Closed
wants to merge 1 commit into from

Conversation

lawnjelly
Copy link
Member

@lawnjelly lawnjelly commented Nov 4, 2019

Existing shadow caster culling using the octree only is very approximate. This PR adds the highly encapsulated class VisualServerLightCuller explicitly to deal with the problem, it is very easy and requires minimal change to use with the existing system and will also work with vulkan branch.

The tests done are very cheap and are unlikely to have any measurable detrimental effect even in extreme circumstances. In game levels using realtime lights the culling will typically offer a modest improvement to FPS, typically around 10%, although frame rate can more than double in some circumstances (directional lights like a sun particularly with PSSM can offer a large improvement).

There is functionality for spotlights, omni and directional.

Notes

  • The culling here is set to occur as a separate additional step after the octree cull. It is possible also to add the extra culling planes to the convex hull used for the octree, but I think this approach will be more efficient (broad phase with the octree, final accurate cull with the light culler).
  • As well as culling shadow casters, there are 2 extra interesting situations that the light culler can detect, which can potentially lead to further (possibly significant) performance gains:
  1. Where there are zero shadow casters, there may be no need for the shadow render pass. However, there is still a need to zero that area of the shadow atlas. Currently it will still do the shadow render pass I believe.
  2. If the call to prepare_light returns false, the light culler has detected that the light cannot possibly cast shadows or light objects within the camera frustum. In this case, there is the opportunity to eliminate the light from the rendering completely.

You can see how it works in this video (ignore the rooms and portals, that is a separate system):
https://www.youtube.com/watch?v=1WT5AXZlsDc

The blue lines from the light sources to the camera frustum show the extra culling planes.

References:

http://lspiroengine.com/?p=153
http://www.terathon.com/gdc06_lengyel.pdf

Note that LSpiro's article deals purely with directional lights, and both these articles rely on dot product - I am dealing with point lights (omni, spotlight) by using a distance to plane function to determine back facing frustum planes rather than dot product. I think this is a better approach than that suggested in the Lengyel article.

The most difficult cases for point lights are where the point is close to the camera frustum (possibility of concave silhouette which would not cull correctly). When the light source is inside the frustum I use a different approach and simply cull the shadow casters to the camera frustum, as any caster outside cannot by definition cast shadows back inside.

Existing shadow caster culling using the octree only is very approximate. This PR adds the highly encapsulated class VisualServerLightCuller explicitly to deal with the problem, it is very easy and requires minimal change to use with the existing system and will also work with vulkan branch.

The tests done are very cheap and are unlikely to have any measurable detrimental effect even in extreme circumstances. In game levels using realtime lights the culling will typically offer a modest improvement to FPS, typically around 10%, although frame rate can more than double in some circumstances (directional lights like a sun particularly with PSSM can offer a large improvement).

There is functionality for spotlights, omni and directional.
@lawnjelly
Copy link
Member Author

Closing this, because although the culling works, there were unforeseen implications for the shadow map caching, i.e. if you render a subset of the light view and the camera moves without the light being made dirty, then the shadow map will be incorrect. This is probably workaroundable, however it would be considerably more involved, and this is going to be changed anyway for 4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants