godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.17k stars 20.21k forks source link

DirectionalLight3D shadow flickers when the camera moves or changes FOV #72015

Open rustwork opened 1 year ago

rustwork commented 1 year ago

Godot version

4.0 Beta 14

System information

Windows 10, Vulkan, Nvidia RTX 3060 Ti

Issue description

If the camera's FOV is animated (for example while sprinting in an FPS game) the shadow flickers. This is most noticeable when the shadow is cast through high frequency alpha tested materials like the leaves of trees.

This problem is made worse as soon as the player gets a bit further from the world origin, likely due to some floating point precision problems. At a relatively small distance of only 500m from the origin there is noticeable flicker of foliage shadows even when the camera is simply moving around normally. It becomes extreme as soon as the camera's FOV changes.

This makes it really difficult to have even a modestly sized outdoor environment without shadow issues.

https://user-images.githubusercontent.com/2095704/214502579-8eb2ea3b-7ca1-457d-8d16-b75c410a567e.mp4

The directional light's settings are pretty standard:

image

Steps to reproduce

From scratch

In example project

Minimal reproduction project

shadow_flicker_bug.zip

clayjohn commented 1 year ago

Which renderer are you using?

Calinou commented 1 year ago

This is an expected issue, which I could reproduce while adding dynamic FOV (depending on car speed) to the Truck Town demo. I worked around this by not changing the camera FOV at low enough speeds. This makes the issue harder to notice as shadow flicker will only occur at high speeds.

I guess this flickering could be fixed by adding a "maximum camera FOV" property to DirectionalLight3D. If set to a value greater than 0, it would adjust the light camera frustum to be suited to the specified field of view, rather than the current camera's field of view (unless the camera's field of view is greater). The default value will be 0 (to avoid reducing shadow quality), so it will require manual configuration if you want to avoid shadow flickering on FOV changes.

Two other notes:

Also, can you check if this is still reproducible after disabling Blend Splits?

Which renderer are you using?

The MRP uses Forward+.

rustwork commented 1 year ago

@Calinou Your maximum FOV proposal sounds like a nice solution for most FOV animation use cases.

To be clear, the shadows in my example are not cast through an Alpha Hash material, it's through an Alpha Scissor material. Changing it to Alpha Hash does indeed make it very jittery. I actually like the quality of the Alpha Scissor shadows, my issue is that even that jitters when the camera is a few hundred meters from the world origin.

Turning off Blend Splits makes no difference, it still flickers the same.