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

Cascaded shadow maps: Fix prepass ortho depth clamping #8877

Merged
merged 2 commits into from
Jun 21, 2023

Conversation

danchia
Copy link
Contributor

@danchia danchia commented Jun 18, 2023

Objective

Solution

Cascaded shadow maps use a technique commonly called shadow pancaking to enhance shadow map resolution by restricting the orthographic projection used in creating the shadow maps to the frustum slice for the cascade. The implication of this restriction is that shadow casters can be closer than the near plane of the projection volume.

Prior to this PR, we address clamp the depth of the prepass vertex output to ensure that these shadow casters do not get clipped, resulting in shadow loss. However, a flaw / bug of the prior approach is that the depth that gets written to the shadow map isn't quite correct - the depth was previously derived by interpolated the clamped clip position, resulting in depths that are further than they should be. This creates artifacts that are particularly noticeable when a very 'long' object intersects the near plane close to perpendicularly.

The fix in this PR is to propagate the unclamped depth to the prepass fragment shader and use that depth value directly.

A complementary solution would be to use DEPTH_CLIP_CONTROL to request unclipped_depth. However due to the relatively low support of the feature on Vulkan (I believe it's ~38%), I went with this solution for now to get the broadest fix out first.


Changelog

  • Fixed: Shadows from directional lights were sometimes incorrectly omitted when the shadow caster was partially out of view.

@danchia danchia added A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior labels Jun 18, 2023
@danchia danchia requested a review from superdump June 18, 2023 08:46
@cart
Copy link
Member

cart commented Jun 18, 2023

Thanks for the quick fix! This does mean that in a directional light shadow pass we're now running the prepass fragment shader of every mesh seen by the directional light right? That seems like a high price to pay for a fix, although I don't have a better solution.

@cart
Copy link
Member

cart commented Jun 18, 2023

Also no clue if this was an issue prior to CSM, but even after this fix there are a few corner cases that get clipped for me (although you really need to hunt for them and they go away with even slight perspective changes):
image

@JMS55 JMS55 added this to the 0.11 milestone Jun 18, 2023
@danchia
Copy link
Contributor Author

danchia commented Jun 18, 2023

Thanks for the quick fix! This does mean that in a directional light shadow pass we're now running the prepass fragment shader of every mesh seen by the directional light right? That seems like a high price to pay for a fix, although I don't have a better solution.

It does, and I too don't see an easy way out of this :(
Using the unclipped_depth flag I described in the PR description would allow us to avoid it on most desktop / native platforms.

That said, I wonder if the GPU side of shadow draws is more draw count / vertex bound and less fragment bound?

@danchia
Copy link
Contributor Author

danchia commented Jun 21, 2023

@cart did you mean to push all the GPU counter commits as well?

@cart
Copy link
Member

cart commented Jun 21, 2023

Haha nope (I was profiling the change). Fixed :)

@danchia
Copy link
Contributor Author

danchia commented Jun 21, 2023

Haha nope (I was profiling the change). Fixed :)

Find anything interesting in the profiles?

Copy link
Member

@cart cart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My profiling couldn't detect a meaningful performance difference in the directional light shadow pass from this change (many_cubes example, but fixed to a specific camera view). Its possible that with more (or different) entities (or more directional lights) this could get more pronounced, but this seems like a reasonable fix for now.

@cart cart enabled auto-merge June 21, 2023 21:51
@cart cart added this pull request to the merge queue Jun 21, 2023
Merged via the queue into bevyengine:main with commit 0a881ab Jun 21, 2023
@JMS55
Copy link
Contributor

JMS55 commented Jul 21, 2023

@danchia wgpu 0.17 will come with gfx-rs/wgpu#3892, will that improve anything?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Directional light shadows disappear when camera is rotated
3 participants