Open Xrayez opened 3 years ago
Thanks for putting some numbers to this, it is very helpful! But I think you are forgetting about scenes where there are a mix of lights with shadows and lights without shadows. The best practice for 2D lights is to only use shadows for light sources that really need it. So you might have shadows from one or two light sources that contribute the most light to the scene, and then smaller light sources (for highlights, and other effects) may not cast shadows.
Performance concerns aside, my preference is to continue treating shadows the same way we do in 3D where shadows are a property of the light source and are disabled by default.
To clarify, I'm not suggesting enabling shadows for every type of light. It's more about the default behavior. We have a lot of stuff enabled by default in the engine, likely in the interest of achieving neat-looking picture/scene out of the box (AFAIK that's the development philosophy of Godot).
We have to talk about in terms of common use case. To me, having shadows by default contributes to the existing notion and expectation that light sources should produce shadows (as in reality), and I believe that should be the most common use case (especially in 3D). Any other use cases require proper configuration, and you're still able to disable shadows if you don't need it, especially when the performance impact is negligible if you don't disable shadows explicitly. Performance was never the highest priority for Godot development, and probably shouldn't be.
With Vulkan backend, perhaps that's where we could reconsider this, as performance will be less of a problem.
In both 2D and 3D, it would likely be possible to automatically determine which lights benefit the most from shadows. We could use the following information to toggle shadows automatically:
To support this, we'd need to turn the Shadow Enabled boolean into an enum with the values Automatic, Always, Never. However, implementing this feature requires a lot of finetuning to get something that works well in most scenarios.
Note: This is unrelated to light LOD; this is about toggling shadows regardless of the distance between the camera and the light.
This is one of the many stumbling blocks where Godot's defaults don't match the beginners expectations. (speaking about Light2D here)
For me the proper way to solve this is by having intuitive defaults that match general user expectations (aka "It just works") the first time the user tries to use a Light2D, and then have a project setting that applies to all Light2D to help those who want to opt-in rather than opt-out)
There is a counterargument for not automatically enabling shadows though (with the exception of DirectionalLight). You don't want to enable shadows for every light in a production game. It causes the number of draw calls to increase significantly, which in turn can make performance plummet. Instead, you should only enable shadows one-by-one after making sure they make a significant enough visual impact (you may be surprised sometimes).
If you look at today's AAA games, you'll spot many lights which have shadows disabled for performance reasons.
Describe the project you are working on
Goost Godot Engine extension.
Describe the problem or limitation you are having in your project
People are confused to see that no shadows are casted with light occluders, and then realize that they simply did not get
shadow_enabled
property enabled inLight2D
for this to work:This is mostly an issue for beginners, but that's also a problem for even experienced developers (I stumbled upon this myself), since there's a notion that
LightOccluder2D
nodes are the ones responsible for casting shadows, and not necessarilyLight2D
nodes, which is not the case. I don't know how it works in other engines.Describe the feature / enhancement and how it helps to overcome the problem or limitation
I propose to enable
shadow_enabled
property by default inLight2D
.Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
200 lights, 50 sprites
No shadows with light occluders
(same result w/o light occluders)
Shadows with light occluders
Shadows w/o light occluders
Conclusion
There's little performance impact of having
shadow_enabled
on without using light occluders (even with thousand of lights), so it might make sense to enable this property by default even if no shadows are actually used (with optimization from the engine side).Test project:
light_2d_shadows_benchmark.zip
If this enhancement will not be used often, can it be worked around with a few lines of script?
Have to enable shadows for each new
Light2D
node every time (unless you use instancing).Is there a reason why this should be core and not an add-on in the asset library?
At first I thought there would be no impact of having shadows enabled without using light occluders which produce them, but I decided to make a proposal anyway to document my research, because this seems to have little performance impact.
That said, there may be something which can be optimized within the engine to completely bypass shadows processing in case no light occluders are used in a project.
This is similar to having ray casting enabled by default (in 4.x): godotengine/godot#31637.
Not sure whether the same rationale applies to 3D.