Add modulate property to lightmaps.#120641
Conversation
Check how #109737 stores the specular intensity property in LightmapGI instead of LightmapGIData. |
|
Implementing it that way has a few issues:
Again, would love to have some feedback on this. |
I find this strange, as this behavior seems to work fine with the specular property added to #109737.
Indeed, that's a limitation of storing the property in both places. That said, I don't expect LightmapGIData resources to be shared across multiple LightmapGI nodes (this never happens if you only rely on the Bake Lightmaps button). |
Also adds `lightmap_get_modulate` as a method to `RenderingServer` to make retrieving the modulate value directly from the lightmap possible as the value in LightmapGI might not be reliable in certain use cases (like if `lightmap_set_modulate` is used).
Yeah, my bad. Missed calling
For my specific use case I might actually end up doing this but since you can still access the modulate value directly using RenderingServer to get the "true" value is this easy to work around. That said, should it be clarified somewhere within the documentation that the module property "desyncing" when re-using LightmapGIData resources is expected behavior? |
Yes, I would mention it in the LightmapGIData property's description. |
Calinou
left a comment
There was a problem hiding this comment.
Tested locally, it works as expected in all renderers. Code looks good to me.
Testing project: test_pr_120641.zip
lightmapgi_modulate_day_night_cycle.webm
| The maximum texture size for the generated texture atlas. Higher values will result in fewer slices being generated, but may not work on all hardware as a result of hardware limitations on texture sizes. Leave [member max_texture_size] at its default value of [code]16384[/code] if unsure. | ||
| </member> | ||
| <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)"> | ||
| The color the lightmap is multiplied with. Gets applied in real-time without the need to re-bake the lightmap. |
There was a problem hiding this comment.
| The color the lightmap is multiplied with. Gets applied in real-time without the need to re-bake the lightmap. | |
| The color the lightmap is multiplied with. Gets applied in real-time without the need to re-bake the lightmap. This can be used to tint indirect lighting (for lights baked with the [constant Light3D.BAKE_DYNAMIC] bake mode). This can be useful for day/night cycles, with the lightmap baked while the [DirectionalLight3D] node is at its "noon" position. Keep in mind other baked light sources (such as environment lighting or the light emitted by emissive materials) will also be affected by the tint. |
There was a problem hiding this comment.
...with the lightmap baked while the [DirectionalLight3D] node is at its "noon" position.
Am kinda confused by this one.
Won't this also bake the shadows of this DirectionalLight3D? I guess the mention of Light3D.BAKE_DYNAMIC implies this light should be set up this way but then why would the positions of a light source not contributing to the lightmap matter at all? For sun direction of the WorldEnvironment?
Or am I misunderstanding how Light3D.BAKE_DYNAMIC interacts with lightmaps? The description for BAKE_DYNAMIC states it only works for VoxelGI and SDFGI.
In all my tests I just set a custom environment for the LightMapGI that's a solid white color. This worth mentioning as an alternative for setting up day/night cycles?
|
I'm not sure if this is a desirable enough feature to be worth the extra shader uniform, code, and maintenance, so I can't comment on whether this is a good idea to merge. But I have some notes on
Source: https://docs.godotengine.org/en/stable/classes/class_color.html I haven't tested this, but from looking at the code, it appears that new public I also see you have a note on the |
|
The reason I did things this way was to avoid doing the conversion every frame in Else we can just keep the |
This is what I had in mind. I think that means we have minimal use of linear-encoded (Performance takes priority, but if it’s the same performance with less linear-encoded |
|
Hello, thank you for opening this pull request, and your effort on it so far. Unfortunately, there are several things not quite aligned right now:
Therefore, we are closing the pull request. If you would like to contribute to Godot, please consider starting with smaller and simpler contributions. Thank you again for your work and sharing it with the Godot community. If/when all of the above are resolved, we can reconsider this feature. |
I hope you reconsider reopening this PR as I feel the reasoning for closing it is deeply unfair and doesn't reflect the needs of the users (not just me). |
|
PR opened 25 June, policy changes announced 30 June, so I think closing this is unfair indeed |
|
The point about the new policy is one out of 3 points Ivorforce mentioned. The remaining points still stand and mean this PR currently doesn't pass the threshold for "should reviewers spend time on this, and should we take on the burden of maintaining it forever if this is merged":
Closing this PR doesn't mean we reject the feature forever, but currently the proposal doesn't meet our criteria for reviewers' limited and already bottlenecked time. |
|
I would agree with you here if 3.x didn't already have a similar feature. Feels weird to me if restoring functionality lost during the transition to a new engine version is deemed as potential bloat unless the removal had a very exlicit reason. (Which to my knowledge wasn't the case here, else #49968 should be closed as an intended change). In godotengine/godot-proposals#11596 Calinou mentioned modulation would offer a potential solution. Hence why I listed it here. I am fully aware the chances of me changing the outcome of this are very slim here. I am just trying to understand the logic as to what seperates my PR from something like #89919 which was in a similar situation. |
What problem(s) does this PR solve?
Adds a color property to lightmaps to multiple the final lightmap by. Effectively giving a limited way to alter the final lighting in real-time. Mostly useful to create day-night cycles but can have various other uses as well.
I already wrote a more detailed reasoning in godotengine/godot-proposals#14722
3.x) #49968Eyecandy, using just LightmapGI and a few gradients to control the sky and lightmap color:

Additional information
Will fully admit, I never touched C++ code so this entire thing is written using pattern observation, my best educated guess work and looking up basic C++ information whenever the syntax didn't make sense.
For the most part I'm pretty certain I did things the right way. The only thing I'm not certain about is how to update the lightmap captures. The problem I'm running into is that, to my knowledge, at no point a lightmap is aware what lightmap instances use it. Which is a problem because
LightStorage::Lightmap::modulatehas to be part ofLightStorage::Lightmapto be accessible in the shader whileRendererSceneCullneeds a lightmap instance to get theRendererSceneCull::InstanceLightmapDatato callRendererSceneCull::_instance_queue_updateon each of its geometries so the lightmap captures get properly updated.So in order for lightmap captures to update whenever
LightStorage::lightmap_set_modulateis called, did I store the lightmap instances for each lightmap inLightStorage::Lightmap::lightmap_instances. This feels like a very bad, hacky and error prone way to do things and requires each time a lightmap is assigned or removed to/from a lightmap instanceLightStorage::lightmap_insert_to_lightmap_instancesand/orLightStorage::lightmap_erase_from_lightmap_instancesto be called.I considered other alternatives but each has their own drawbacks. Would love to have feedback on this. There is very non-zero chance I missed a better option here!
Also not sure about the UX. Because
LightStorage::Lightmap::modulateis part of the lightmap does it appear underData/light_dataas part of theLightmapGIDatarather than underTweakswhere I feel it would be more logical. But to store the modulate property in both the LightmapGI node and theLightmapGIDataand carefully having to cover each scenario where these two might get out of sync doesn't sound great either. Not to mention it making it confusing where the modulate property is actually used.