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

Reset SDFGI when changing editor scene tabs #81167

Merged
merged 1 commit into from
Oct 25, 2023

Conversation

bitsawer
Copy link
Member

Resets SDFGI when user changes scenes in the editor. Previously, users could sometimes see reflections, occlusion or GI from another, completely unrelated scene. This is well shown in the issue video or MRP (use the third project, sdfgi test3.zip). The issue project is an extreme case, but it explains some issues people have been complaining about. For example, after tuning and adjusting a scene lighting and coming back later the scene can look completely different (because back then it was partially or completely using SDFGI data from another scene).

This also adds RenderingServer::sdfgi_reset() to perform this reset. I'm not completely familiar with RenderingServer internals, so feedback is welcome. I implemented a simple a I think robust way to reset SDFGI, but I can see a few other ways it could be implemented.

Also, it would be useful to expose this to scripting too as people have to do this when changing their game scenes. I can do that now or in another PR if we want to think about the public API more (related issue #39961, although in this PR we only add complete reset functionality). Currently, doing the reset in GDScript is pretty tricky and looking for the right, active WorldEnvironment node and its resource can be hard for general tools scripts. Then you have to do a double wait (process+render) for cover all cases (like if the Gogot window is minimized or if the node gets freed during the wait etc.), so you have to do something like this:

world.environment.sdfgi_enabled = false

await get_tree().process_frame
await RenderingServer.frame_post_draw

world.environment.sdfgi_enabled = true

Copy link
Contributor

@YuriSizov YuriSizov left a comment

Choose a reason for hiding this comment

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

Editor part seems fine.

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

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

Wouldn't it be enough to just clear all the SDFGI textures? I'm a bit concerned about deleting and re-allocating all the textures just to effectively clear them all to default values.

@bitsawer
Copy link
Member Author

bitsawer commented Oct 6, 2023

The SDFGI currently doesn't have any easy way to gently reset the textures, even other existing code just deletes and re-creates the SDFGI object when needed. For example here:

static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
if (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) {
//configuration changed, erase
sdfgi.unref();
rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
}
if (sdfgi.is_null()) {
// re-create
sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size);
rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
} else {
//check for updates
sdfgi->update(p_environment, p_world_position);
}

I could try add some kind of texture clear reset version if none of the cascade size etc. parameters have changed, but it probably won't be worth it in this case (changing tabs, where a full reset is always needed).

However, if we want to expose this to scripting in a future PR, it might be worth investigating and benchmarking this. Although in those theoretical cases users will only usually call it when changing the level etc., in which cases a full reset is usually needed anyway, so the performance gain can be pretty theoretical.

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

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

Ah, okay. Fair enough. You shouldn't have to refactor SDFGI just to implement this.

@akien-mga akien-mga merged commit f021d33 into godotengine:master Oct 25, 2023
16 checks passed
@akien-mga
Copy link
Member

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.

SDFGI propagating light to other scenes and reflections (also not updating until movement)
4 participants