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

Add a fixed-position, fixed-size last shadow split option in DirectionalLight3D to improve quality in small/medium-sized levels #7590

Open
Calinou opened this issue Aug 31, 2023 · 1 comment

Comments

@Calinou
Copy link
Member

Calinou commented Aug 31, 2023

Describe the project you are working on

The Godot editor 🙂

Describe the problem or limitation you are having in your project

In Godot, all shadow splits follow the camera. This is a good approach for open world games, but it can fall short in games with closed level designs, especially when you can see far away in the distance. Shadow splits cover a limited distance from the camera's position, so you may not see any shadows when looking far away:

image

This tends to incentivize users to greatly increase Shadow Max Distance to cover the entire level (while also setting Fade Start to 1.0 to maximize its potential), but this comes at a quality and performance cost as all shadow splits need to be stretched out accordingly. Manual shadow split tuning can help somewhat, but this isn't something most users perform as it's relatively complicated to get right.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a fixed-size last shadow split option in DirectionalLight3D.

Example in Trackmania 20201, with a free camera that has a very low FOV to make it easier to notice:

tm.mp4

This is technically feasible because the level has a fixed size, with the last shadow split being at a fixed position and covering the stadium:

out webp

Therefore, no matter how far away the camera is, the last split's shadows will always be visible on the stadium. This comes at no performance or quality cost, just the shadow frustum being optimally located.

Some benefits of using a fixed frustum for the shadow split:

There are some downsides though:

  • This is most suited to closed level designs of a small or medium size, not open world games.
  • The last fixed split's size must be configured manually by the user (or generated using an editor tool, as described below).
  • The last split has to cover the entire level, including what's behind the camera. This means shadow texel density will be lower than with a dynamic split approach that may not cover the entire level. That said, since this is intended to be used for static objects, the increased pixelation artifacts won't be too noticeable. Also consider that with a fixed split, you can often decrease Shadow Max Distance to a lower value without affecting quality much.
  • If objects can draw shadows outside this fixed split, the last split will not contain any shadows for them. Dynamic objects should still be able to cast shadows up close though, as the first split(s) continue to follow the camera with this option enabled.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This would likely be exposed as a boolean in DirectionalLight3D to enable fixed-size last shadow split (only when shadows are enabled). When enabled, you can see another Last Split AABB property, or a Last Split Size Vector3 property centered around the DirectionalLight3D's origin. We can provide an editor helper to automatically fit its extents to the world geometry (VoxelGI could benefit from that too).

The option should work with all shadow split modes (orthogonal, PSSM 2 Splits, PSSM 4 Splits). The last split is the only split affected by the option. When using orthogonal, it'll effectively affect the entire shadow rendering. Fade Start is ignored and hidden in the inspector when the option is enabled.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No.

Is there a reason why this should be core and not an add-on in the asset library?

This is about improving built-in shadow rendering, which is a core feature.

Footnotes

  1. Every Trackmania game since Sunrise has used this approach, so it's not exactly a new thing to do 🙂

@Calinou Calinou changed the title Add a fixed-size last shadow split option in DirectionalLight3D Add a fixed-position, fixed-size last shadow split option in DirectionalLight3D Aug 31, 2023
@Calinou Calinou changed the title Add a fixed-position, fixed-size last shadow split option in DirectionalLight3D Add a fixed-position, fixed-size last shadow split option in DirectionalLight3D to improve quality in small/medium-sized levels Aug 31, 2023
@QbieShay
Copy link

QbieShay commented Sep 1, 2023

Yes! This is a very good approach. Had the same problem recently and tried to figure out solutions for faraway background objects to still get shadowed. yes please :D

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

No branches or pull requests

2 participants