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

Expose method LightmapGI.bake() in editor and exported projects #8656

Open
guerro323 opened this issue Dec 15, 2023 · 6 comments · May be fixed by godotengine/godot#91676
Open

Expose method LightmapGI.bake() in editor and exported projects #8656

guerro323 opened this issue Dec 15, 2023 · 6 comments · May be fixed by godotengine/godot#91676

Comments

@guerro323
Copy link

Describe the project you are working on

I'm working on a procedural and UGC (User Generated Content) game where users can create their own maps from premade blocks and custom models.

Describe the problem or limitation you are having in your project

I need to have lightmaps for performance and look reasons as I'm targeting both low and high end PCs.
As it is a game where users can create their own maps from premade blocks (or their own) in a map editor ingame this mean I cannot use the editor for that.

Since GPUs become faster and faster everyday and that LightmapGI uses GPU for baking, this is perfect for this proposal!

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Exposing the method help for procedural and UGC games:

  • The user wouldn't need to download a whole editor and a project just to bake lights of their maps, it would be seamless ingame.
  • For procedural scenes that require realistic lighting or lighting which cannot be provided by SDFGI or VoxelGI alone, having lightmaps unlock that.

Having the bake method exposed also help for the editor side:

  • You could have a script which bake multiple scenes at a time, saving time and letting you do other things (such as sleeping if you're baking a dozen of maps at high quality).
  • You could automate and test lightmap changes (such as bounce, bounce feedback, ...) and which output a screenshot, saving a lot of time and effort.
  • You could have a tool which apply some stuff before baking and restore them later (eg: occluders that should be visible in the bake but hidden after that)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Code A:

Based on how LightmapGIEditorPlugin does it:

func on_bake_step(step_progress: float, step_description: String) -> bool:
    return Input.is_key_pressed(KEY_ESCAPE) # Cancel if the user pressed the escape key

# LightmapGI.bake(bake_step_callback: Callable, from_node: Node = null)
var err: BakeError = lm.bake(on_bake_step)

Code B:

More understandable and traditional for developers:

func start_baking():
    # LightmapGI.bake_start(from_node: Node = null)
    var err: BakeError = lm.bake_start() # If there is an error, the baking will stop immediately

func _process(delta):
    if lm.is_baking:
        # LightmapGI.bake_status() -> {step_progress=0.0, step_description="", error=BakeError}
        var status: Dictionary = lm.bake_status()
        if Input.is_key_pressed(KEY_ESCAPE): # Cancel if the user pressed the escape key
            lm.bake_abort()

Code B is my preferred choice and make more sense for developers, especially if you check the next note ↓

Note: as of right now, I'm not sure how Godot does to call process while the lightmap is baking as it should be blocking by looking at the code (but throwing a tool script it does call process...), so the method where you call it is blocking which could cause problems if badly implemented on the game code (such as an infinite loop).
Note: the bake or bake_start require a LightmapGIData to be set in the node or else it should return an error. Perhaps passing one in the method parameter could be done.

As of right now, it's not possible to cancel lightmapping (even thought it has a dedicated error) but I think canceling it should be implemented, mainly for those reasons:

  • If you do a batch bake in the editor, you need to be able to cancel or else you may loose the progress of previous scenes bake.
  • For a game, if the user want to quit the game or abort the baking process they should be able to do so and not resort to kill the game process.

As I've read on this issue godotengine/godot#59217 (which is only for exposing it to editor) this would increase the binary size on exported projects:
To solve that, a feature would be added in the Build Configuration Profile window with the name Lightmapping. It would be disabled by default and would require the game maker to enable it manually.
If disabled and the bake method is called, an error will pop out in the console indicating what the user should do and bake would return BakeError.BAKE_ERROR_NO_LIGHTMAPPER.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No.

Is there a reason why this should be core and not an add-on in the asset library?

LightmapGI is core.

@Calinou
Copy link
Member

Calinou commented Dec 15, 2023

To solve that, a feature would be added in the Build Configuration Profile window with the name Lightmapping. It would be disabled by default and would require the game maker to enable it manually.

This should also be done for UV2 unwrapping using xatlas, which you'll probably need if you wish to bake lightmaps in an exported project.

@Calinou
Copy link
Member

Calinou commented Apr 12, 2024

I tried my hand at exposing LightmapGI runtime baking (only in editor builds for now), but I couldn't get it to work: https://github.com/Calinou/godot/tree/lightmapgi-expose-baking

Feel free to continue this branch if you'd like 🙂

@RisingThumb
Copy link

RisingThumb commented May 3, 2024

I tried my hand at exposing LightmapGI runtime baking (only in editor builds for now), but I couldn't get it to work: https://github.com/Calinou/godot/tree/lightmapgi-expose-baking

Feel free to continue this branch if you'd like 🙂

Hey @Calinou , I spent a little bit of time digging into why this doesn't work, and I've narrowed the issue down a little bit.
The issue seems to happen on this particular line: https://github.com/godotengine/godot/blob/master/scene/3d/lightmap_gi.cpp#L1168

I haven't had the time yet to go through the ResourceLoader object and see why imports might be failing when running the game, but is fine while in the editor. I suspect the issue is to do with the ResourceLoader/importing and not the approach taken here.
EDIT: I've looked a little into the ResourceLoader from the docs. Importing can't be done at runtime, so I'm fairly confident this is the issue here

@RisingThumb
Copy link

Hey folks,
I've thrown together something that works for runtime baking. See this commit: https://github.com/RisingThumb/RisingThumb-Godot/commit/c969526d0f93781abfd1e6e3af948aa830a7b9cf
It's not perfect mind, there's several changes here that I'm unhappy with. First was using .png instead of .exr. This was only because it was easier to work with, but I should be able to add it back(I think I had some weird import issues with it, but I can't remember). Secondly is with this spot of code

	// We can't use resource saver for the gi_data in-game
	// I'd like to save it though... TODO: Add an else condition!
	if (Engine::get_singleton()->is_editor_hint()) {
		Error err = ResourceSaver::save(gi_data);

		if (err != OK) {
			return BAKE_ERROR_CANT_CREATE_IMAGE;
		}
	}

Ideally we can save the resource while in-game, but that doesn't currently seem to be possible. Am I missing something here with ResourceSaver?

@Calinou
Copy link
Member

Calinou commented May 5, 2024

This was only because it was easier to work with, but I should be able to add it back(I think I had some weird import issues with it, but I can't remember).

Godot can't save OpenEXR in release builds; this is only enabled on editor builds for binary size reasons. We could add a SCons option to allow saving OpenEXR in exported projects: godotengine/godot#73003

That said, for runtime baking, you could save to Godot's own texture format (that is, a .ctex or .res file). This works in exported projects, even for HDR pixel formats.

Note that in both cases, exported projects can't perform VRAM texture compression (they can only decompress). This is also reserved to editor builds for binary size reasons. VRAM compression is currently not used by default in lightmapping, but godotengine/godot#91535 would make it fast enough to be viable as a default.

@RisingThumb
Copy link

RisingThumb commented May 5, 2024

Thanks for the pointers on this Calinou, you can see all the changes so far in this commit:
V-Sekai/godot@1ef3cdb
I reverted back to using .exr files for baking in-editor, however baking in-game it now saves to a .res file. Since the importer can't be used in-game or in exported binaries(unless I'm missing something...). I also fixed the resource saving for .lmbake files, it seems to be something to do with the path getting mangled at runtime? Getting the basename and adding .lmbake on the end and passing it to the ResourceSaver works for this.

There is 1 issue with this commit that I've not been able to narrow down yet. When a lightmapGI has environment mode set to Scene(the default) or Custom Sky, the lightmap texture ends up mangled, BUT only when baking at runtime(in editor this still ends up fine). When set to disabled, this doesn't seem to happen 😕

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

Successfully merging a pull request may close this issue.

3 participants