From ddc3126bbf5bc5397a0d702cc3f91fc4118ba95a Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 18 Sep 2023 11:56:04 -0300 Subject: [PATCH] Add half-pixel offset to lightmapper rasterization. Add half-pixel offset to lightmapper to fix issues where the ray would be generated from the wrong spot corresponding to the pixel and causing light leaks. Fixes Issue #69126. --- modules/lightmapper_rd/lightmapper_rd.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 748e8ae50ca..4ed730b3af7 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -589,8 +589,12 @@ void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int raster_push_constant.grid_size[0] = grid_size; raster_push_constant.grid_size[1] = grid_size; raster_push_constant.grid_size[2] = grid_size; - raster_push_constant.uv_offset[0] = 0; - raster_push_constant.uv_offset[1] = 0; + + // Half pixel offset is required so the rasterizer doesn't output face edges directly aligned into pixels. + // This fixes artifacts where the pixel would be traced from the edge of a face, causing half the rays to + // be outside of the boundaries of the geometry. See . + raster_push_constant.uv_offset[0] = -0.5f / float(atlas_size.x); + raster_push_constant.uv_offset[1] = -0.5f / float(atlas_size.y); RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); //draw opaque @@ -1579,8 +1583,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d { seams_push_constant.base_index = seam_offset; rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline); - seams_push_constant.uv_offset[0] = uv_offsets[0].x / float(atlas_size.width); - seams_push_constant.uv_offset[1] = uv_offsets[0].y / float(atlas_size.height); + seams_push_constant.uv_offset[0] = (uv_offsets[0].x - 0.5f) / float(atlas_size.width); + seams_push_constant.uv_offset[1] = (uv_offsets[0].y - 0.5f) / float(atlas_size.height); seams_push_constant.blend = uv_offsets[0].z; rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant)); @@ -1603,8 +1607,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d for (int j = 1; j < uv_offset_count; j++) { seams_push_constant.base_index = seam_offset; - seams_push_constant.uv_offset[0] = uv_offsets[j].x / float(atlas_size.width); - seams_push_constant.uv_offset[1] = uv_offsets[j].y / float(atlas_size.height); + seams_push_constant.uv_offset[0] = (uv_offsets[j].x - 0.5f) / float(atlas_size.width); + seams_push_constant.uv_offset[1] = (uv_offsets[j].y - 0.5f) / float(atlas_size.height); seams_push_constant.blend = uv_offsets[0].z; rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));