Skip to content

Commit 219035c

Browse files
committed
Fix LightmapGI shadow leaks
1 parent 42c7f14 commit 219035c

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

modules/lightmapper_rd/lightmapper_rd.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise_oidn(RenderingDevice *p_rd, RID
979979
return BAKE_OK;
980980
}
981981

982-
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, void *p_bake_userdata) {
982+
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, RID p_unocclude_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, void *p_bake_userdata) {
983983
RID denoise_params_buffer = p_rd->uniform_buffer_create(sizeof(DenoiseParams));
984984
DenoiseParams denoise_params;
985985
denoise_params.spatial_bandwidth = 5.0f;
@@ -1000,8 +1000,15 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
10001000
}
10011001
{
10021002
RD::Uniform u;
1003-
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
1003+
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
10041004
u.binding = 3;
1005+
u.append_id(p_unocclude_tex);
1006+
uniforms.push_back(u);
1007+
}
1008+
{
1009+
RD::Uniform u;
1010+
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
1011+
u.binding = 4;
10051012
u.append_id(denoise_params_buffer);
10061013
uniforms.push_back(u);
10071014
}
@@ -1622,6 +1629,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
16221629
}
16231630

16241631
PushConstant push_constant;
1632+
push_constant.denoiser_range = p_use_denoiser ? p_denoiser_range : 1.0;
16251633

16261634
/* UNOCCLUDE */
16271635
{
@@ -1638,7 +1646,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
16381646
RD::Uniform u;
16391647
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
16401648
u.binding = 1;
1641-
u.append_id(unocclude_tex); //will be unused
1649+
u.append_id(unocclude_tex);
16421650
uniforms.push_back(u);
16431651
}
16441652
}
@@ -1659,6 +1667,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
16591667
rd->compute_list_end(); //done
16601668
}
16611669

1670+
#ifdef DEBUG_TEXTURES
1671+
for (int i = 0; i < atlas_slices; i++) {
1672+
Vector<uint8_t> s = rd->texture_get_data(unocclude_tex, i);
1673+
Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s);
1674+
img->save_exr("res://1_unocclude_" + itos(i) + ".exr", false);
1675+
}
1676+
#endif
1677+
16621678
if (p_step_function) {
16631679
if (p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true)) {
16641680
FREE_TEXTURES
@@ -2083,7 +2099,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
20832099
} else {
20842100
// JNLM (built-in).
20852101
SWAP(light_accum_tex, light_accum_tex2);
2086-
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, p_bake_userdata);
2102+
error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, unocclude_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, p_bake_sh, p_step_function, p_bake_userdata);
20872103
}
20882104
if (unlikely(error != BAKE_OK)) {
20892105
return error;
@@ -2098,7 +2114,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
20982114
} else {
20992115
// JNLM (built-in).
21002116
SWAP(shadowmask_tex, shadowmask_tex2);
2101-
error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, shadowmask_tex2, normal_tex, shadowmask_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, false, p_step_function, p_bake_userdata);
2117+
error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, shadowmask_tex2, normal_tex, shadowmask_tex, unocclude_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, false, p_step_function, p_bake_userdata);
21022118
}
21032119
if (unlikely(error != BAKE_OK)) {
21042120
return error;

modules/lightmapper_rd/lightmapper_rd.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ class LightmapperRD : public Lightmapper {
261261
uint32_t ray_to = 0;
262262
uint32_t region_ofs[2] = {};
263263
uint32_t probe_count = 0;
264-
uint32_t pad = 0;
264+
uint32_t denoiser_range = 0;
265265
};
266266

267267
Vector<Ref<Image>> lightmap_textures;
@@ -289,7 +289,7 @@ class LightmapperRD : public Lightmapper {
289289
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);
290290

291291
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);
292-
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, void *p_bake_userdata);
292+
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, RID p_unocclude_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, void *p_bake_userdata);
293293
BakeError _pack_l1(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);
294294

295295
Error _store_pfm(RenderingDevice *p_rd, RID p_atlas_tex, int p_index, const Size2i &p_atlas_size, const String &p_name, bool p_shadowmask);

modules/lightmapper_rd/lm_compute.glsl

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ layout(set = 1, binding = 2) uniform texture2D environment;
4646
#ifdef MODE_UNOCCLUDE
4747

4848
layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position;
49-
layout(rgba32f, set = 1, binding = 1) uniform restrict readonly image2DArray unocclude;
49+
layout(rgba32f, set = 1, binding = 1) uniform restrict image2DArray unocclude;
5050

5151
#endif
5252

@@ -73,7 +73,8 @@ layout(set = 1, binding = 1) uniform texture2DArray source_light;
7373

7474
#ifdef MODE_DENOISE
7575
layout(set = 1, binding = 2) uniform texture2DArray source_normal;
76-
layout(set = 1, binding = 3) uniform DenoiseParams {
76+
layout(set = 1, binding = 3) uniform texture2DArray unocclude_mask;
77+
layout(set = 1, binding = 4) uniform DenoiseParams {
7778
float spatial_bandwidth;
7879
float light_bandwidth;
7980
float albedo_bandwidth;
@@ -93,6 +94,7 @@ layout(push_constant, std430) uniform Params {
9394

9495
ivec2 region_ofs;
9596
uint probe_count;
97+
uint denoiser_range;
9698
}
9799
params;
98100

@@ -995,13 +997,16 @@ void main() {
995997

996998
vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent);
997999
float min_d = 1e20;
1000+
float unocclude_mask = 0.0;
1001+
9981002
for (int i = 0; i < 4; i++) {
999-
vec3 ray_to = base_pos + rays[i] * texel_size;
1003+
vec3 ray_to = base_pos + rays[i] * texel_size * params.denoiser_range;
10001004
float d;
10011005
vec3 norm;
10021006

10031007
if (trace_ray_closest_hit_distance(base_pos, ray_to, d, norm) == RAY_BACK) {
1004-
if (d < min_d) {
1008+
unocclude_mask = 1.0;
1009+
if (d <= texel_size && d < min_d) {
10051010
// This bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back.
10061011
vertex_pos = base_pos + rays[i] * d + norm * bake_params.bias * 10.0;
10071012
min_d = d;
@@ -1012,6 +1017,7 @@ void main() {
10121017
position_alpha.xyz = vertex_pos;
10131018

10141019
imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha);
1020+
imageStore(unocclude, ivec3(atlas_pos, params.atlas_slice), vec4(unocclude_mask, 0, 0, 0));
10151021

10161022
#endif
10171023

@@ -1195,6 +1201,7 @@ void main() {
11951201
vec3 search_rgb = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(search_pos, lightmap_slice), 0).rgb;
11961202
vec3 search_albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).rgb;
11971203
vec3 search_normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).xyz;
1204+
float search_occlusion = texelFetch(sampler2DArray(unocclude_mask, linear_sampler), ivec3(search_pos, params.atlas_slice), 0).r;
11981205
float patch_square_dist = 0.0f;
11991206
for (int offset_y = -HALF_PATCH_WINDOW; offset_y <= HALF_PATCH_WINDOW; offset_y++) {
12001207
for (int offset_x = -HALF_PATCH_WINDOW; offset_x <= HALF_PATCH_WINDOW; offset_x++) {
@@ -1236,12 +1243,16 @@ void main() {
12361243
float normal_square_dist = dot(normal_delta, normal_delta);
12371244
weight *= exp(-normal_square_dist / TWO_SIGMA_NORMAL_SQUARE);
12381245

1246+
// Weight with occlusion.
1247+
weight *= 1.0 - search_occlusion;
1248+
12391249
denoised_rgb += weight * search_rgb;
12401250
sum_weights += weight;
12411251
}
12421252
}
12431253

1244-
denoised_rgb /= sum_weights;
1254+
// Avoid division by zero if no weights were accumulated.
1255+
denoised_rgb = sum_weights > EPSILON ? denoised_rgb / sum_weights : input_rgb;
12451256
} else {
12461257
// Ignore pixels where the normal is empty, just copy the light color.
12471258
denoised_rgb = input_light.rgb;

0 commit comments

Comments
 (0)