From de9b22625ea255a01cd03b16cc4b827555f26c51 Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Tue, 26 Aug 2025 00:28:43 +0200 Subject: [PATCH] LightmapGI: Pack L1 SH coefficients before denoising --- modules/lightmapper_rd/lightmapper_rd.cpp | 17 ++++++----- modules/lightmapper_rd/lightmapper_rd.h | 3 +- modules/lightmapper_rd/lm_compute.glsl | 37 +++++++++-------------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index a5608dab1a0..a51a9a15381 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -980,6 +980,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Refbuffer_update(denoise_params_buffer, 0, sizeof(DenoiseParams), &denoise_params); Vector uniforms = dilate_or_denoise_common_uniforms(p_source_light_tex, p_dest_light_tex); @@ -2065,6 +2066,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d /* DENOISE */ + if (p_bake_sh) { + SWAP(light_accum_tex, light_accum_tex2); + BakeError error = _pack_l1(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices); + if (unlikely(error != BAKE_OK)) { + return error; + } + } + if (p_use_denoiser) { if (p_step_function) { if (p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true)) { @@ -2290,14 +2299,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } } - if (p_bake_sh) { - SWAP(light_accum_tex, light_accum_tex2); - BakeError error = _pack_l1(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices); - if (unlikely(error != BAKE_OK)) { - return error; - } - } - #ifdef DEBUG_TEXTURES for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index 5a1e5a81f2f..0111318176f 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -281,7 +281,8 @@ class LightmapperRD : public Lightmapper { int half_search_window; float filter_strength; - float pad[2]; + uint32_t slice_count; + uint32_t pad; }; BakeError _blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector> &albedo_images, Vector> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, float p_supersampling_factor, BakeStepFunc p_step_function, void *p_bake_userdata); diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index 3e40315b216..e44dfc10af8 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -82,6 +82,7 @@ layout(set = 1, binding = 4) uniform DenoiseParams { int half_search_window; float filter_strength; + uint slice_count; } denoise_params; #endif @@ -1193,13 +1194,9 @@ void main() { const float FILTER_SQUARE_TWO_SIGMA_LIGHT_SQUARE = FILTER_VALUE * FILTER_VALUE * TWO_SIGMA_LIGHT_SQUARE; const float EPSILON = 1e-6f; -#ifdef USE_SH_LIGHTMAPS - const uint slice_count = 4; + const uint slice_count = denoise_params.slice_count; const uint slice_base = params.atlas_slice * slice_count; -#else - const uint slice_count = 1; - const uint slice_base = params.atlas_slice; -#endif + const bool is_directional = (slice_count == 4); for (uint i = 0; i < slice_count; i++) { uint lightmap_slice = slice_base + i; @@ -1223,9 +1220,16 @@ void main() { for (int offset_x = -HALF_PATCH_WINDOW; offset_x <= HALF_PATCH_WINDOW; offset_x++) { ivec2 offset_input_pos = atlas_pos + ivec2(offset_x, offset_y); ivec2 offset_search_pos = search_pos + ivec2(offset_x, offset_y); - vec3 offset_input_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(offset_input_pos, lightmap_slice), 0).rgb; - vec3 offset_search_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(offset_search_pos, lightmap_slice), 0).rgb; + vec3 offset_input_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(offset_input_pos, slice_base), 0).rgb; + vec3 offset_search_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(offset_search_pos, slice_base), 0).rgb; vec3 offset_delta_rgb = offset_input_rgb - offset_search_rgb; + + if (is_directional) { + // Since L0 data is 1/4 the value of a regular lightmap, + // we have to multiply it by 4. + offset_delta_rgb *= 4.0; + } + patch_square_dist += dot(offset_delta_rgb, offset_delta_rgb) - TWO_SIGMA_LIGHT_SQUARE; } } @@ -1280,24 +1284,13 @@ void main() { #ifdef MODE_PACK_L1_COEFFS vec4 base_coeff = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice * 4), 0); + imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice * 4), base_coeff); for (int i = 1; i < 4; i++) { vec4 c = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice * 4 + i), 0); + c.rgb /= (base_coeff.rgb * 8.0 + vec3(1e-6f)); + c.rgb = clamp(c.rgb + vec3(0.5), vec3(0.0), vec3(1.0)); - if (abs(base_coeff.r) > 0.0) { - c.r /= (base_coeff.r * 8); - } - - if (abs(base_coeff.g) > 0.0) { - c.g /= (base_coeff.g * 8); - } - - if (abs(base_coeff.b) > 0.0) { - c.b /= (base_coeff.b * 8); - } - - c.rgb += vec3(0.5); - c.rgb = clamp(c.rgb, vec3(0.0), vec3(1.0)); imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice * 4 + i), c); } #endif