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 #13833

Closed
wants to merge 46 commits into from
Closed

Cascaded Shadow Maps #13833

wants to merge 46 commits into from

Conversation

x2048
Copy link
Contributor

@x2048 x2048 commented Sep 22, 2023

Upgrades the current shadow mapping implementation to cascaded shadow maps.

Benefits:

  • Affine transformation for the shadow = simpler math, faster shader, less maintenance
  • Fixes shadows for large objects/meshes such as e.g. in Little Lady or shadows for clouds in the future
  • Smoother updates of shadows (every cascade updates at its own pace, cascade 0 updates every frame)
  • Much less peter-panning
  • Less VRAM consumption for similar shadow quality/scale
  • Visible area covered with shadows in most cases even with fast camera movement

Other fixes:

  • Removed flicker when mapblock is updated (e.g. flowing water)
  • Removed flicker when camera offset changes (every 200 nodes)
  • Added bilinear filter for SHADOW_FILTER == 1 for playable shadow quality with more performance

Notes:

  • 3 cascades
  • Cascade 0 is fixed small size in world and updates every frame, giving reasonable shadow quality close to the player
  • Cascade 2 is updated every shadow_update_frames frame (up to 32) and cascade 1 somewhere in-between
  • Entity shadows on cascades 0 and 1
  • Colored shadows work
  • Soft shadows work (may need some tuning)
  • Shadow performance with client_mesh_chunk_size = 1 may be lower because of increased number of drawcalls covering larger area. Increasing shadow_update_frames should help spread out the updates.
  • shadow_map_texture_size now controls resolution of each of 3 cascades (2 for entities) and should be divided by 2 when migrating

To do

This PR is Ready for Review.

  • Testing needed
  • Tuning/defaults feedback needed

How to test

  1. Turn on the shadows
  2. Enter a game that supports shadows
  3. Check the shadows both at close and long distance, when flying etc.

Fixes the leaves of the trees but breaks grass
@x2048 x2048 added @ Client / Audiovisuals Roadmap: Needs approval The change is not part of the current roadmap and needs to be approved by coredevs beforehand. labels Sep 22, 2023
@x2048 x2048 self-assigned this Sep 22, 2023
@x2048 x2048 added Feature ✨ PRs that add or enhance a feature Testing needed labels Sep 22, 2023
@lhofhansl
Copy link
Contributor

lhofhansl commented Sep 24, 2023

Nice!

Some observations... There's a visible change between Cascade 0 and 1 (i.e. as approach a shadow of a larger object there's a visible discontinuity). I also saw some "phantom shadows", as you approach an area without shadow there appear circle shaped darker areas. (I'll see if I can do a short video of that).
It seems plant shadow are only in Cascade 0...?

@lhofhansl
Copy link
Contributor

I think the cascade default distances might be too small. And I cannot easily figure out where the distances are actually set for each cascade.

@rubenwardy rubenwardy added the Adoption needed The pull request needs someone to adopt it. Adoption welcomed! label Oct 2, 2023
@Zughy Zughy removed the Roadmap: Needs approval The change is not part of the current roadmap and needs to be approved by coredevs beforehand. label Oct 9, 2023
@lhofhansl
Copy link
Contributor

lhofhansl commented Oct 20, 2023

Just so I remember later... The cascade max distance is set here:

void DirectionalLight::update_frustum(const Camera *cam, Client *client, bool force, u8 max_cascades)
{
	client->getEnv().getClientMap().allocateDrawListShadowCascades(getCascadesCount());

	f32 scale = 20. * BS / getFarValue();
	f32 scale_factor = 1./pow(scale, 1./(cascades.size() - 1.));

	for (auto &cascade: cascades) {
		cascade.farPlane = farPlane;
		cascade.scale = scale;
		scale *= scale_factor;
	}

So if viewing_range would 100, the first cascade would end at 20, the next one at around 45, and the last at 100.
For 1000, it be again at 20, then 140, then 1000. Etc.

If we wanted the smaller cascades to reach farther we'd change it to
f32 scale = 40. * BS / getFarValue(); .. or something.

Or maybe we'd start with scale just set to 0.1 (i.e. 1/10 of the viewing range), or 0.2.

@lhofhansl
Copy link
Contributor

With a changed distance calculation I'm more happy with this.

Still have to look into the "phantom shadow"/moire effects with cascade 0 - as time permits.

@Zughy Zughy unassigned x2048 Oct 20, 2023
@lhofhansl
Copy link
Contributor

lhofhansl commented Oct 25, 2023

I need to slog through a lot of code to understand which bias I need to tweak to eliminate any fake shadows.

After this PR:
screenshot_20231021_145934

Notice the round-ish extra dark artifact on the cliff and that the overall scene is darker.

Before this PR:
screenshot_20231021_150209

@lhofhansl
Copy link
Contributor

lhofhansl commented Nov 5, 2023

Setting the z perspective bias to 0.25 instead of 0.5 gets rid of the "fake" shadows.

@lhofhansl
Copy link
Contributor

lhofhansl commented Nov 5, 2023

I'll file a separate PR, starting with x2048 and my changes on top as separate commits.

@lhofhansl
Copy link
Contributor

Continued in #13956
We can close this one. The initial commit there is of course credited to @x2048 !

@rubenwardy rubenwardy closed this Nov 5, 2023
@wsor4035 wsor4035 removed the Adoption needed The pull request needs someone to adopt it. Adoption welcomed! label Dec 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants