Skip to content

Conversation

@superdump
Copy link
Contributor

@superdump superdump commented Dec 25, 2025

Objective

Solution

  • The search radius used on main simplified down to the light_size / cascade_diameter. The light size could be tweaked for this to look ok, but the softness of the shadows would be unintuitive for cascaded shadow maps given the interplay between the cascade configuration and the light size - if you change one you would have to tweak the other.
  • Instead, it seems this works much better if one uses 128.0f / shadow_map_size equivalent to 128 texels, where shadow_map_size is the texture dimensions of the cascade. At least for the shadow map size we use. Given all cascades use the same resolution, this is practically a constant: 128.0 / 2048.0 = 0.0625 in UV units. This means that each cascade will search smaller or larger regions for blockers depending on how close they are to the camera. It does feel like the blocker search. This came from this MIT-licensed code: https://github.com/PanosK92/SpartanEngine/blob/f0526aac0ed3197cc3ffb09d029f8b3bde8daf21/data/shaders/shadow_mapping.hlsl#L106
  • I observed 'ghost' shadows when only changing the search radius, so I added in random rotations of the blocker search sampling kernel to avoid this.

Testing

I've tested using the pcss example on an M4 Max.


Showcase

Soft shadows off:
Screenshot 2025-12-25 at 22 57 57

PCSS main:
Screenshot 2025-12-25 at 22 58 01

PCSS on this PR:
Screenshot 2025-12-25 at 23 03 25
Note how the shadow is harder at the base of the tree and softer around the leaves. I don't have a ground truth image of this scene to compare to, but this is at least more how it should be.

This results in the PCSS soft shadows being harder close to the contact of the object with the receiving surface, and softer when there is more distance between them.
This removes some 'ghost' shadows that otherwise appear.
@superdump
Copy link
Contributor Author

This is a draft because I'm not super convinced by this approach yet for the following reasons:

  • Why does a blocker search radius of 128 texels always work? Should it be a constant of 0.0625 UV units always? Should it be a configurable number of texels such that if people change the shadow map resolution, the PCSS blocker search radius in texels is also or can also be adjusted?
  • I think it needs testing across more different configurations and scenes. I may throw something together with a bunch of trees of different sizes and different distances from the camera, but not too dense, so that the shadows can be seen.
  • The noise patterns in the shadows aren't great. Also in the mentioned MIT code is use of a golden spiral sampling kernel. It seems that Jimenez 2014 does use spirals with interleaved gradient noise random rotations, but apparently the golden spiral is ideal. Could be worth trying. I wonder if a different random rotation approach could be less jarring too. Perhaps blue noise random rotations.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant