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

SDFGI: Add method to regenerate data (instead of completely reinitializing) #39961

Closed
Tracked by #55327
31 opened this issue Jun 29, 2020 · 7 comments
Closed
Tracked by #55327

SDFGI: Add method to regenerate data (instead of completely reinitializing) #39961

31 opened this issue Jun 29, 2020 · 7 comments

Comments

@31
Copy link
Contributor

31 commented Jun 29, 2020

Godot version: 481151b (playing with master)

Issue description:
I want to use SDFGI with procedural static geometry, and right now I have to toggle sdfgi_enabled off and on to regenerate voxel/baked data when I add new geometry. This usually brings in some garbage memory, causing bright flashes (especially in a dark scene). I can cover it up with a loading screen for some scenarios, but this limits more dynamic games that e.g. dynamically generate more geometry as you move along.

There should be an API that lets me mark the data for regen, even better if it takes an AABB for a specific region.

Discussed with @reduz on IRC. 👍

@Calinou
Copy link
Member

Calinou commented Nov 11, 2021

Still reproducible as of c89061e. It can be noticed when changing the number of SDFGI cascades at run-time (or even within the editor). Bright flashes will occasionally happen, but not always.

Testing project: global_illumination.zip

Epilepsy warning: Video with bright flashes
sdfgi-cascade-change-bright-flash.mp4

Shouldn't we just initialize the GI data to be fully black to avoid this bright flash? This would at least resolve the issue partially and make it easier to cover up.

@31
Copy link
Contributor Author

31 commented Nov 11, 2021

Shouldn't we just initialize the GI data to be fully black to avoid this bright flash?

I agree, the things I had in mind for this issue were:

  • Always initialize to 0 to avoid unpredictable behavior based on garbage memory.
  • Add an API to reset the data (ideally in a specific AABB) without needing to touch SDFGI settings at all.

The first part could be implemented without the second part. (Maybe it could be split off from this issue.)

@Calinou
Copy link
Member

Calinou commented Nov 11, 2021

Always initialize to 0 to avoid unpredictable behavior based on garbage memory.

I had a brief look within https://github.com/godotengine/godot/blob/11e03ae7f085b53505c242cf92615f7170c779ce/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp, but I couldn't find where I should clear the textures. For instance, here's one instance where it's currently done:

//clear these textures, as they will have previous garbage on next draw
RD::get_singleton()->texture_clear(cascades[cascade].light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
RD::get_singleton()->texture_clear(cascades[cascade].light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
RD::get_singleton()->texture_clear(cascades[cascade].light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);

@SmartySmart702
Copy link

Is it planned for SDFGI to be able to "smoothly" update in realtime (over multiple frames)?
Please correct me if I'm wrong but right now SDFGI works only for generated levels where you have a loading screen or something but you cannot use it for a game where the player can place objects into the level that are affected by SDFGI (I mean you can use it but it will always start from 0 and will update over multiple frames and that's probably not what you want).

@Calinou
Copy link
Member

Calinou commented May 18, 2022

Is it planned for SDFGI to be able to "smoothly" update in realtime (over multiple frames)?

Support for dynamic occluders is planned in a future 4.x release, but not in 4.0.

That said, for the "user-placed object" use case, you may not need support for dynamic occluders. Supporting partial SDFGI regeneration (using an AABB specified by the developer) would go a long way already, as long as the texture is properly cleaned up as mentioned above.

Please correct me if I'm wrong but right now SDFGI works only for generated levels where you have a loading screen or something but you cannot use it for a game where the player can place objects into the level that are affected by SDFGI (I mean you can use it but it will always start from 0 and will update over multiple frames and that's probably not what you want).

This is indeed the case. You can force SDFGI to regenerate by disabling it and enabling it again, but this causes flickering (which should be hidden using some kind of transition). Even if the texture is properly cleaned up, the scene will still appear to be darkened for a few frames.

You can get faster SDFGI generation speed at the cost of worse lighting quality by decreasing Frames To Converge in the Project Settings. You can then increase lighting quality without affecting the number of frames to converge by increasing Probe Ray Count, but this has a significant performance cost.

@Calinou
Copy link
Member

Calinou commented Sep 15, 2023

You can get faster SDFGI generation speed at the cost of worse lighting quality by decreasing Frames To Converge in the Project Settings. You can then increase lighting quality without affecting the number of frames to converge by increasing Probe Ray Count, but this has a significant performance cost.

Regarding this, I've created a script-based workaround below. It works well for outdoor scenes with mostly rough materials, but it makes reflections appear too bright while SDFGI is still converging. Indoor scenes also suffer from lots of visible noise while it's still converging (this is expected, as it's a more difficult scenario for light bounces).

extends Node3D

@export var prevent_fade_in = true

@onready var environment: Environment = $WorldEnvironment.environment

# Default value in frames set in the Project Settings. Change accordingly if you use a non-default value.
var sdfgi_frames_to_converge: int = 30

# The frame number on which the anti-fade in was reset.
var started_converge_frame := 0


func _process(delta: float) -> void:
	if prevent_fade_in:
		environment.sdfgi_energy = clamp(
				float(sdfgi_frames_to_converge) / (Engine.get_frames_drawn() - started_converge_frame),
				1.0,
				sdfgi_frames_to_converge
			)
		print(environment.sdfgi_energy)


func _input(event: InputEvent) -> void:
	if event.is_action_pressed(&"toggle_sdfgi"):
		environment.sdfgi_enabled = not environment.sdfgi_enabled

		if environment.sdfgi_enabled:
			reset_prevent_fade_in()


func reset_prevent_fade_in() -> void:
	started_converge_frame = Engine.get_frames_drawn()

@Calinou
Copy link
Member

Calinou commented Sep 19, 2023

Closing in favor of godotengine/godot-proposals#7741, as feature proposals are now tracked in the Godot proposals repository.

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

6 participants