diff --git a/light/ltface.cc b/light/ltface.cc index 30c81678..26eccc4d 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -2613,6 +2613,70 @@ IntegerDownsampleImage(const std::vector &input, int w, int h, int facto return res; } +static std::vector +FloodFillTransparent(const std::vector &input, int w, int h) +{ + // transparent pixels take the average of their neighbours. + + std::vector res(input); + + while (1) { + int unhandled_pixels = 0; + + for (int y=0; y= w) + continue; + if (y1 < 0 || y1 >= h) + continue; + + const qvec4f neighbourSample = res.at((y1 * w) + x1); + if (neighbourSample[3] == 1) { + opaque_neighbours++; + neighbours_sum += qvec3f(neighbourSample); + } + } + } + + if (opaque_neighbours > 0) { + neighbours_sum *= (1.0f / (float)opaque_neighbours); + res.at(i) = qvec4f(neighbours_sum[0], neighbours_sum[1], neighbours_sum[2], 1.0f); + + // this sample is now opaque + } else { + unhandled_pixels++; + + // all neighbours are transparent. need to perform more iterations (or the whole lightmap is transparent). + } + } + } + } + + if (unhandled_pixels == input.size()) { + logprint("FloodFillTransparent: warning, fully transparent lightmap\n"); + break; + } + + if (unhandled_pixels == 0) + break; // all done + } + + return res; +} + static std::vector HighlightSeams(const std::vector &input, int w, int h) { @@ -2808,6 +2872,9 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const fullres = HighlightSeams(fullres, oversampled_width, oversampled_height); } + // removes all transparent pixels by averaging from adjacent pixels + fullres = FloodFillTransparent(fullres, oversampled_width, oversampled_height); + if (softsamples > 0) { fullres = BoxBlurImage(fullres, oversampled_width, oversampled_height, softsamples); }