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

Avoid calculating dynamic lights when lights are already baked using the static bake mode in the Forward+ renderer #96771

Merged
merged 1 commit into from
Dec 10, 2024

Conversation

clayjohn
Copy link
Member

@clayjohn clayjohn commented Sep 9, 2024

Fixes an issue related to: #85145

When baking a light with the static bake mode, the light is calculated twice. Once when baking and once at runtime. The light values are added together resulting in double lighting.

Shadows are already skipped using the exact same code, but the actual lighting was still being added.

Opening as draft as I need to check the mobile renderer and the compatibility renderer

@clayjohn clayjohn added this to the 4.4 milestone Sep 9, 2024
@Calinou
Copy link
Member

Calinou commented Sep 18, 2024

For context, there's already a skip in place here for directional lights:

if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
continue; // Statically baked light and object uses lightmap, skip
}

It does the job when shadows are enabled, but not when shadows are disabled. This PR fixes double lighting in Forward+ when using a DirectionalLight3D with shadows disabled (although note that its shadows will be baked anyway).

To clarify, the bug I mentioned in #85145 does not occur in Forward+ (neither in 4.3.stable nor master), only in Mobile. To fix #85145, we need to add the same logic used in Forward+ in Mobile (there are no instances of LIGHT_BAKE_STATIC in scene_forward_mobile.glsl currently).

I've tested this PR locally and it fixes double lighting when shadows are disabled on a DirectionalLight3D in Forward+.

@clayjohn
Copy link
Member Author

That other check only disables shadows. The lighting was added in either case.

For the mobile renderer the check shouldn't be in the shader, it should be excluding the light from the light list when pairing with the object so we don't get any overhead from the light at all

@clayjohn clayjohn marked this pull request as ready for review November 23, 2024 02:03
@clayjohn clayjohn requested a review from a team as a code owner November 23, 2024 02:03
@clayjohn
Copy link
Member Author

@Calinou Updated!

In the end this was the situation:

  1. Forward+ was missing the check for the light portion (it was only checked for shadows and the flag was only passed in when shadows were enabled)
  2. Mobile was missing the check everywhere. The correct space to add it is in the shader for directional lights, but during pairing for positional lights
  3. Compatibility did the check for positional lights after pairing, so the check became redundant.

It should be ready to go now!

@clayjohn clayjohn requested a review from Calinou November 23, 2024 02:12
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, it mostly works as expected in all rendering methods. Performance increases as expected when baking with the Static bake mode as opposed to the default Dynamic.

Testing project: test_lightmapgi_mobile.zip

There's one issue where DirectionalLight3D with shadow disabled still applies double lighting, but only in Compatibility:

DirectionalLight3D shadow enabled (Compatibility)

image

DirectionalLight3D shadow enabled (Compatibility)

image

OmniLight3D and SpotLight3D don't have this issue in Compatibility.

@clayjohn
Copy link
Member Author

clayjohn commented Dec 6, 2024

@Calinou Thanks for checking! It turned out that the vertex lighting codepath in the GLES3 shader was missing the check. I added it and removed the static checks for omnilights and spotlights since they weren't necessary anymore.

This should be ready to go now!

@clayjohn clayjohn requested a review from Calinou December 6, 2024 18:19
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great now 🙂

@@ -2211,6 +2211,10 @@ void fragment_shader(in SceneData scene_data) {
continue; //not masked
}

if (directional_lights.data[i].bake_mode == LIGHT_BAKE_STATIC && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) {
continue; // Statically baked light and object uses lightmap, skip
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
continue; // Statically baked light and object uses lightmap, skip
continue; // Statically baked light and object uses lightmap, skip.

@Repiteo Repiteo merged commit a167afd into godotengine:master Dec 10, 2024
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Dec 10, 2024

Thanks!

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

Successfully merging this pull request may close these issues.

4 participants