Skip to content

Commit e7bd1b0

Browse files
committed
Add denoiser range property for LightmapGI
1 parent 1d47561 commit e7bd1b0

File tree

7 files changed

+39
-14
lines changed

7 files changed

+39
-14
lines changed

doc/classes/LightmapGI.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
<member name="camera_attributes" type="CameraAttributes" setter="set_camera_attributes" getter="get_camera_attributes">
2929
The [CameraAttributes] resource that specifies exposure levels to bake at. Auto-exposure and non exposure properties will be ignored. Exposure settings should be used to reduce the dynamic range present when baking. If exposure is too high, the [LightmapGI] will have banding artifacts or may have over-exposure artifacts.
3030
</member>
31+
<member name="denoiser_range" type="int" setter="set_denoiser_range" getter="get_denoiser_range" default="10">
32+
The distance in pixels from which the denoiser samples. Lower values preserve more details, but may give blotchy results if the lightmap quality is not high enough. Only effective if [member use_denoiser] is [code]true[/code] and [member ProjectSettings.rendering/lightmapping/denoising/denoiser] is set to JNLM.
33+
</member>
3134
<member name="denoiser_strength" type="float" setter="set_denoiser_strength" getter="get_denoiser_strength" default="0.1">
3235
The strength of denoising step applied to the generated lightmaps. Only effective if [member use_denoiser] is [code]true[/code] and [member ProjectSettings.rendering/lightmapping/denoising/denoiser] is set to JNLM.
3336
</member>

modules/lightmapper_rd/lightmapper_rd.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ void LightmapperRD::_sort_triangle_clusters(uint32_t p_cluster_size, uint32_t p_
226226
}
227227
}
228228

229-
Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata) {
229+
Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata) {
230230
Vector<Size2i> sizes;
231231

232232
for (int m_i = 0; m_i < mesh_instances.size(); m_i++) {
@@ -261,7 +261,7 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_
261261
source_sizes.resize(sizes.size());
262262
source_indices.resize(sizes.size());
263263
for (int i = 0; i < source_indices.size(); i++) {
264-
source_sizes.write[i] = sizes[i] + Vector2i(2, 2); // Add padding between lightmaps
264+
source_sizes.write[i] = sizes[i] + Vector2i(2, 2).maxi(p_denoiser_range); // Add padding between lightmaps
265265
source_indices.write[i] = i;
266266
}
267267
Vector<Vector3i> atlas_offsets;
@@ -906,14 +906,15 @@ LightmapperRD::BakeError LightmapperRD::_denoise_oidn(RenderingDevice *p_rd, RID
906906
return BAKE_OK;
907907
}
908908

909-
LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function) {
909+
LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function) {
910910
RID denoise_params_buffer = p_rd->uniform_buffer_create(sizeof(DenoiseParams));
911911
DenoiseParams denoise_params;
912912
denoise_params.spatial_bandwidth = 5.0f;
913913
denoise_params.light_bandwidth = p_denoiser_strength;
914914
denoise_params.albedo_bandwidth = 1.0f;
915915
denoise_params.normal_bandwidth = 0.1f;
916916
denoise_params.filter_strength = 10.0f;
917+
denoise_params.half_search_window = p_denoiser_range;
917918
p_rd->buffer_update(denoise_params_buffer, 0, sizeof(DenoiseParams), &denoise_params);
918919

919920
Vector<RD::Uniform> uniforms = dilate_or_denoise_common_uniforms(p_source_light_tex, p_dest_light_tex);
@@ -976,7 +977,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
976977
return BAKE_OK;
977978
}
978979

979-
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization) {
980+
LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization) {
980981
int denoiser = GLOBAL_GET("rendering/lightmapping/denoising/denoiser");
981982
String oidn_path = EDITOR_GET("filesystem/tools/oidn/oidn_denoise_path");
982983

@@ -1008,7 +1009,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
10081009
Vector<Ref<Image>> albedo_images;
10091010
Vector<Ref<Image>> emission_images;
10101011

1011-
BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_step_function, p_bake_userdata);
1012+
BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, p_denoiser_range, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_step_function, p_bake_userdata);
10121013
if (bake_error != BAKE_OK) {
10131014
return bake_error;
10141015
}
@@ -1793,7 +1794,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
17931794
} else {
17941795
// JNLM (built-in).
17951796
SWAP(light_accum_tex, light_accum_tex2);
1796-
error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, atlas_size, atlas_slices, p_bake_sh, p_step_function);
1797+
error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, p_bake_sh, p_step_function);
17971798
}
17981799
if (unlikely(error != BAKE_OK)) {
17991800
return error;

modules/lightmapper_rd/lightmapper_rd.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,17 @@ class LightmapperRD : public Lightmapper {
262262
float albedo_bandwidth;
263263
float normal_bandwidth;
264264

265+
int half_search_window;
265266
float filter_strength;
266-
float pad[3];
267+
float pad[2];
267268
};
268269

269-
BakeError _blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata);
270+
BakeError _blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata);
270271
void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, uint32_t p_cluster_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &r_triangle_indices_buffer, RID &r_cluster_indices_buffer, RID &r_cluster_aabbs_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata);
271272
void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform);
272273

273274
BakeError _dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices);
274-
BakeError _denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function);
275+
BakeError _denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function);
275276

276277
Error _store_pfm(RenderingDevice *p_rd, RID p_atlas_tex, int p_index, const Size2i &p_atlas_size, const String &p_name);
277278
Ref<Image> _read_pfm(const String &p_name);
@@ -283,7 +284,7 @@ class LightmapperRD : public Lightmapper {
283284
virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) override;
284285
virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) override;
285286
virtual void add_probe(const Vector3 &p_position) override;
286-
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0) override;
287+
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0) override;
287288

288289
int get_bake_texture_count() const override;
289290
Ref<Image> get_bake_texture(int p_index) const override;

modules/lightmapper_rd/lm_compute.glsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ layout(set = 1, binding = 3) uniform DenoiseParams {
7676
float albedo_bandwidth;
7777
float normal_bandwidth;
7878

79+
int half_search_window;
7980
float filter_strength;
8081
}
8182
denoise_params;
@@ -849,10 +850,10 @@ void main() {
849850

850851
// Half the size of the patch window around each pixel that is weighted to compute the denoised pixel.
851852
// A value of 1 represents a 3x3 window, a value of 2 a 5x5 window, etc.
852-
const int HALF_PATCH_WINDOW = 4;
853+
const int HALF_PATCH_WINDOW = 3;
853854

854855
// Half the size of the search window around each pixel that is denoised and weighted to compute the denoised pixel.
855-
const int HALF_SEARCH_WINDOW = 10;
856+
const int HALF_SEARCH_WINDOW = denoise_params.half_search_window;
856857

857858
// For all of the following sigma values, smaller values will give less weight to pixels that have a bigger distance
858859
// in the feature being evaluated. Therefore, smaller values are likely to cause more noise to appear, but will also

scene/3d/lightmap_gi.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
11021102
}
11031103
}
11041104

1105-
Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, denoiser_strength, bounces, bounce_indirect_energy, bias, max_texture_size, directional, use_texture_for_bounces, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization);
1105+
Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, denoiser_strength, denoiser_range, bounces, bounce_indirect_energy, bias, max_texture_size, directional, use_texture_for_bounces, Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization);
11061106

11071107
if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_TOO_SMALL) {
11081108
return BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL;
@@ -1450,6 +1450,14 @@ float LightmapGI::get_denoiser_strength() const {
14501450
return denoiser_strength;
14511451
}
14521452

1453+
void LightmapGI::set_denoiser_range(int p_denoiser_range) {
1454+
denoiser_range = p_denoiser_range;
1455+
}
1456+
1457+
int LightmapGI::get_denoiser_range() const {
1458+
return denoiser_range;
1459+
}
1460+
14531461
void LightmapGI::set_directional(bool p_enable) {
14541462
directional = p_enable;
14551463
}
@@ -1593,6 +1601,9 @@ void LightmapGI::_validate_property(PropertyInfo &p_property) const {
15931601
if (p_property.name == "denoiser_strength" && !use_denoiser) {
15941602
p_property.usage = PROPERTY_USAGE_NONE;
15951603
}
1604+
if (p_property.name == "denoiser_range" && !use_denoiser) {
1605+
p_property.usage = PROPERTY_USAGE_NONE;
1606+
}
15961607
}
15971608

15981609
void LightmapGI::_bind_methods() {
@@ -1638,6 +1649,9 @@ void LightmapGI::_bind_methods() {
16381649
ClassDB::bind_method(D_METHOD("set_denoiser_strength", "denoiser_strength"), &LightmapGI::set_denoiser_strength);
16391650
ClassDB::bind_method(D_METHOD("get_denoiser_strength"), &LightmapGI::get_denoiser_strength);
16401651

1652+
ClassDB::bind_method(D_METHOD("set_denoiser_range", "denoiser_range"), &LightmapGI::set_denoiser_range);
1653+
ClassDB::bind_method(D_METHOD("get_denoiser_range"), &LightmapGI::get_denoiser_range);
1654+
16411655
ClassDB::bind_method(D_METHOD("set_interior", "enable"), &LightmapGI::set_interior);
16421656
ClassDB::bind_method(D_METHOD("is_interior"), &LightmapGI::is_interior);
16431657

@@ -1661,6 +1675,7 @@ void LightmapGI::_bind_methods() {
16611675
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
16621676
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
16631677
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "denoiser_strength", PROPERTY_HINT_RANGE, "0.001,0.2,0.001,or_greater"), "set_denoiser_strength", "get_denoiser_strength");
1678+
ADD_PROPERTY(PropertyInfo(Variant::INT, "denoiser_range", PROPERTY_HINT_RANGE, "1,20"), "set_denoiser_range", "get_denoiser_range");
16641679
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
16651680
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texel_scale", PROPERTY_HINT_RANGE, "0.01,100.0,0.01"), "set_texel_scale", "get_texel_scale");
16661681
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size");

scene/3d/lightmap_gi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class LightmapGI : public VisualInstance3D {
156156
BakeQuality bake_quality = BAKE_QUALITY_MEDIUM;
157157
bool use_denoiser = true;
158158
float denoiser_strength = 0.1f;
159+
int denoiser_range = 10;
159160
int bounces = 3;
160161
float bounce_indirect_energy = 1.0;
161162
float bias = 0.0005;
@@ -256,6 +257,9 @@ class LightmapGI : public VisualInstance3D {
256257
void set_denoiser_strength(float p_denoiser_strength);
257258
float get_denoiser_strength() const;
258259

260+
void set_denoiser_range(int p_denoiser_range);
261+
int get_denoiser_range() const;
262+
259263
void set_directional(bool p_enable);
260264
bool is_directional() const;
261265

scene/3d/lightmapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ class Lightmapper : public RefCounted {
180180
virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) = 0;
181181
virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) = 0;
182182
virtual void add_probe(const Vector3 &p_position) = 0;
183-
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, float p_exposure_normalization = 1.0) = 0;
183+
virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_step_userdata = nullptr, float p_exposure_normalization = 1.0) = 0;
184184

185185
virtual int get_bake_texture_count() const = 0;
186186
virtual Ref<Image> get_bake_texture(int p_index) const = 0;

0 commit comments

Comments
 (0)