Merge pull request #50827 from Calinou/bakedlightmap-add-bounce-indirect-energy

This commit is contained in:
Rémi Verschelde 2021-07-27 10:44:41 +02:00 committed by GitHub
commit 6a6b6fa5cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 34 additions and 8 deletions

View file

@ -5,6 +5,7 @@
</brief_description>
<description>
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.
</description>
<tutorials>
<link>https://docs.godotengine.org/en/3.3/tutorials/3d/baked_lightmaps.html</link>
@ -30,10 +31,14 @@
Maximum size of each lightmap layer, only used when [member atlas_generate] is enabled.
</member>
<member name="bias" type="float" setter="set_bias" getter="get_bias" default="0.005">
Raycasting bias used during baking to avoid floating point precission issues.
Raycasting bias used during baking to avoid floating point precision issues.
</member>
<member name="bounce_indirect_energy" type="float" setter="set_bounce_indirect_energy" getter="get_bounce_indirect_energy" default="1.0">
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].
</member>
<member name="bounces" type="int" setter="set_bounces" getter="get_bounces" default="3">
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].
</member>
<member name="capture_cell_size" type="float" setter="set_capture_cell_size" getter="get_capture_cell_size" default="0.5">
Grid size used for real-time capture information on dynamic objects.

View file

@ -66,7 +66,8 @@
<member name="cell_subdiv" type="int" setter="set_cell_subdiv" getter="get_cell_subdiv" default="1">
</member>
<member name="energy" type="float" setter="set_energy" getter="get_energy" default="1.0">
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.
</member>
<member name="interior" type="bool" setter="set_interior" getter="is_interior" default="false">
Controls whether dynamic capture objects receive environment lighting or not.

View file

@ -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<Vector3> &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<Image> &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<Image> &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;

View file

@ -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<Image> 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<Image> &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<Image> &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<Image> get_bake_texture(int p_index) const;

View file

@ -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;

View file

@ -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;

View file

@ -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<Image> &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<Image> &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<Image> get_bake_texture(int p_index) const = 0;