From 974d3aa9cd5da61dcddf51158e8876a7571f4408 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sun, 25 Jul 2021 02:55:36 +0200 Subject: [PATCH] Add a property to control the bounce indirect energy in BakedLightmap Higher values will make indirect lighting brighter. A value of 1.0 represents physically accurate behavior, but higher values can be used to make indirect lighting propagate more visibly when using a low number of bounces. This can be used to speed up bake times by lowering the number of bounces then increasing the bounce indirect energy. Unlike BakedLightmapData's energy property, this property does not affect direct lighting emitted by light nodes or emissive materials. --- doc/classes/BakedLightmap.xml | 9 +++++++-- doc/classes/BakedLightmapData.xml | 3 ++- modules/lightmapper_cpu/lightmapper_cpu.cpp | 5 +++-- modules/lightmapper_cpu/lightmapper_cpu.h | 3 ++- scene/3d/baked_lightmap.cpp | 16 +++++++++++++++- scene/3d/baked_lightmap.h | 4 ++++ scene/3d/lightmapper.h | 2 +- 7 files changed, 34 insertions(+), 8 deletions(-) diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml index f7d280f36f6..eba1ae6bd4b 100644 --- a/doc/classes/BakedLightmap.xml +++ b/doc/classes/BakedLightmap.xml @@ -5,6 +5,7 @@ Baked lightmaps are an alternative workflow for adding indirect (or baked) lighting to a scene. Unlike the [GIProbe] approach, baked lightmaps work fine on low-end PCs and mobile devices as they consume almost no resources in run-time. + [b]Note:[/b] Due to how lightmaps work, most properties only have a visible effect once lightmaps are baked again. https://docs.godotengine.org/en/3.3/tutorials/3d/baked_lightmaps.html @@ -30,10 +31,14 @@ Maximum size of each lightmap layer, only used when [member atlas_generate] is enabled. - Raycasting bias used during baking to avoid floating point precission issues. + Raycasting bias used during baking to avoid floating point precision issues. + + + The energy multiplier for each bounce. Higher values will make indirect lighting brighter. A value of [code]1.0[/code] represents physically accurate behavior, but higher values can be used to make indirect lighting propagate more visibly when using a low number of bounces. This can be used to speed up bake times by lowering the number of [member bounces] then increasing [member bounce_indirect_energy]. Unlike [member BakedLightmapData.energy], this property does not affect direct lighting emitted by light nodes, emissive materials and the environment. + [b]Note:[/b] [member bounce_indirect_energy] only has an effect if [member bounces] is set to a value greater than or equal to [code]1[/code]. - Number of light bounces that are taken into account during baking. + Number of light bounces that are taken into account during baking. See also [member bounce_indirect_energy]. Grid size used for real-time capture information on dynamic objects. diff --git a/doc/classes/BakedLightmapData.xml b/doc/classes/BakedLightmapData.xml index ea68fabcfac..3dcbe79be7b 100644 --- a/doc/classes/BakedLightmapData.xml +++ b/doc/classes/BakedLightmapData.xml @@ -66,7 +66,8 @@ - Global energy multiplier for baked and dynamic capture objects. + Global energy multiplier for baked and dynamic capture objects. This can be changed at run-time without having to bake lightmaps again. + To adjust only the energy of indirect lighting (without affecting direct lighting or emissive materials), adjust [member BakedLightmap.bounce_indirect_energy] and bake lightmaps again. Controls whether dynamic capture objects receive environment lighting or not. diff --git a/modules/lightmapper_cpu/lightmapper_cpu.cpp b/modules/lightmapper_cpu/lightmapper_cpu.cpp index 0ff8afdf388..e19c9096ee3 100644 --- a/modules/lightmapper_cpu/lightmapper_cpu.cpp +++ b/modules/lightmapper_cpu/lightmapper_cpu.cpp @@ -897,7 +897,7 @@ void LightmapperCPU::_compute_indirect_light(uint32_t p_idx, void *r_lightmap) { color += throughput * sample.emission; throughput *= sample.albedo; - color += throughput * sample.direct_light; + color += throughput * sample.direct_light * parameters.bounce_indirect_energy; // Russian Roulette // https://computergraphics.stackexchange.com/questions/2316/is-russian-roulette-really-the-answer @@ -1256,7 +1256,7 @@ void LightmapperCPU::_blit_lightmap(const Vector &p_src, const Vector2i p_dst->unlock(); } -LightmapperCPU::BakeError LightmapperCPU::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, BakeStepFunc p_substep_function) { +LightmapperCPU::BakeError LightmapperCPU::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bounce_indirect_energy, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, BakeStepFunc p_substep_function) { if (p_step_function) { bool cancelled = p_step_function(0.0, TTR("Begin Bake"), p_bake_userdata, true); if (cancelled) { @@ -1272,6 +1272,7 @@ LightmapperCPU::BakeError LightmapperCPU::bake(BakeQuality p_quality, bool p_use parameters.use_denoiser = p_use_denoiser; parameters.bias = p_bias; parameters.bounces = p_bounces; + parameters.bounce_indirect_energy = p_bounce_indirect_energy; parameters.environment_transform = p_environment_transform; parameters.environment_panorama = p_environment_panorama; diff --git a/modules/lightmapper_cpu/lightmapper_cpu.h b/modules/lightmapper_cpu/lightmapper_cpu.h index 503a09c1344..7f64b3f8611 100644 --- a/modules/lightmapper_cpu/lightmapper_cpu.h +++ b/modules/lightmapper_cpu/lightmapper_cpu.h @@ -82,6 +82,7 @@ class LightmapperCPU : public Lightmapper { struct BakeParams { float bias; int bounces; + float bounce_indirect_energy; int samples; bool use_denoiser = true; Ref environment_panorama; @@ -169,7 +170,7 @@ public: virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size); virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size); virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size); - virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, BakeStepFunc p_substep_function = nullptr); + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bounce_energy, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, BakeStepFunc p_substep_function = nullptr); int get_bake_texture_count() const; Ref get_bake_texture(int p_index) const; diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 23584ec501a..e1f631c4be6 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -815,7 +815,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_sa bool gen_atlas = OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2 ? false : generate_atlas; - Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bias, gen_atlas, max_atlas_size, environment_image, environment_xform, _lightmap_bake_step_function, &bsud, bake_substep_function); + Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bounce_indirect_energy, bias, gen_atlas, max_atlas_size, environment_image, environment_xform, _lightmap_bake_step_function, &bsud, bake_substep_function); if (bake_err != Lightmapper::BAKE_OK) { switch (bake_err) { @@ -1412,6 +1412,15 @@ int BakedLightmap::get_bounces() const { return bounces; } +void BakedLightmap::set_bounce_indirect_energy(float p_indirect_energy) { + ERR_FAIL_COND(p_indirect_energy < 0.0); + bounce_indirect_energy = p_indirect_energy; +} + +float BakedLightmap::get_bounce_indirect_energy() const { + return bounce_indirect_energy; +} + void BakedLightmap::set_bias(float p_bias) { ERR_FAIL_COND(p_bias < 0.00001f); bias = p_bias; @@ -1460,6 +1469,9 @@ void BakedLightmap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces); ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces); + ClassDB::bind_method(D_METHOD("set_bounce_indirect_energy", "bounce_indirect_energy"), &BakedLightmap::set_bounce_indirect_energy); + ClassDB::bind_method(D_METHOD("get_bounce_indirect_energy"), &BakedLightmap::get_bounce_indirect_energy); + ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias); ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias); @@ -1524,6 +1536,7 @@ void BakedLightmap::_bind_methods() { ADD_GROUP("Tweaks", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bounce_indirect_energy", "get_bounce_indirect_energy"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_color"), "set_use_color", "is_using_color"); @@ -1583,6 +1596,7 @@ BakedLightmap::BakedLightmap() { capture_propagation = 1; capture_enabled = true; bounces = 3; + bounce_indirect_energy = 1.0; image_path = ""; set_disable_scale(true); capture_cell_size = 0.5; diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h index fa4f5c1b5b3..438c7a89d5c 100644 --- a/scene/3d/baked_lightmap.h +++ b/scene/3d/baked_lightmap.h @@ -163,6 +163,7 @@ private: int max_atlas_size; bool capture_enabled; int bounces; + float bounce_indirect_energy; bool use_denoiser; bool use_hdr; bool use_color; @@ -266,6 +267,9 @@ public: void set_bounces(int p_bounces); int get_bounces() const; + void set_bounce_indirect_energy(float p_indirect_energy); + float get_bounce_indirect_energy() const; + void set_bias(float p_bias); float get_bias() const; diff --git a/scene/3d/lightmapper.h b/scene/3d/lightmapper.h index 1ca81ab9765..80b8d1a411b 100644 --- a/scene/3d/lightmapper.h +++ b/scene/3d/lightmapper.h @@ -179,7 +179,7 @@ public: virtual void add_directional_light(bool p_bake_direct, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_size) = 0; virtual void add_omni_light(bool p_bake_direct, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_size) = 0; virtual void add_spot_light(bool p_bake_direct, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_multiplier, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size) = 0; - virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, BakeStepFunc p_substep_function = nullptr) = 0; + virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bounce_indirect_energy, float p_bias, bool p_generate_atlas, int p_max_texture_size, const Ref &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, BakeStepFunc p_substep_function = nullptr) = 0; virtual int get_bake_texture_count() const = 0; virtual Ref get_bake_texture(int p_index) const = 0;