From 5cf8612699961f4149448dfd43ad0ae6b007ad9a Mon Sep 17 00:00:00 2001 From: mm00 Date: Thu, 3 Apr 2025 20:49:44 +0200 Subject: [PATCH] Fixed directional blur --- SDFMapCreator/Program.cs | 39 +++++++++++++++------- SDFMapCreator/SdfKernels.Kernels.cs | 51 ++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/SDFMapCreator/Program.cs b/SDFMapCreator/Program.cs index 082c163..2528203 100644 --- a/SDFMapCreator/Program.cs +++ b/SDFMapCreator/Program.cs @@ -29,12 +29,14 @@ public static class Program { Console.WriteLine("Debug mode enabled."); } + var imagesPath = "images"; for (var i = 0; i < 8; i++) { var pixels = ImageUtil.LoadImage($"./{imagesPath}{Path.DirectorySeparatorChar}{i + 1:00}.png"); Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1))); } -/* + + /* var pixels = ImageUtil.LoadImage($"./sphereempty.png"); Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1))); pixels = ImageUtil.LoadImage($"./spherehalf.png"); @@ -54,6 +56,18 @@ public static class Program { width = (uint)Images[0].Width; height = (uint)Images[0].Height; + for (int i = 1; i < Images.Count; i++) { + for (int x = 0; x < Images[i].Width; x++) { + for (int y = 0; y < Images[i].Height; y++) { + Images[i].Pixels[x, y].X = MathF.Min(Images[i - 1].Pixels[x, y].X + Images[i].Pixels[x, y].X, MAX); + Images[i].Pixels[x, y].Y = MathF.Min(Images[i - 1].Pixels[x, y].Y + Images[i].Pixels[x, y].X, MAX); + Images[i].Pixels[x, y].Z = MathF.Min(Images[i - 1].Pixels[x, y].Z + Images[i].Pixels[x, y].X, MAX); + } + } + + if(debug)Images[i].Pixels.SaveImage($"Debug/Sum{i}.png"); + } + Console.WriteLine("Creating masks..."); for (var i = 0; i < Images.Count; i++) { //for each image pair, create a mask var selfMask = SelfMask(Images[i].Pixels); @@ -113,18 +127,22 @@ public static class Program { } currStep += stepIncrement; } + + finalImage.SaveImage("Debug/Final.png"); // apply directional blur - var iterations = 10; - var radius = 3f; + var iterations = 1; + var radius = 100f; var step = .5f; var sigma = 1f; + var totalMask = SelfMask(Images[^1].Pixels); + totalMask.SaveImage("Debug/TotalMask.png"); for (var i = 0; i < iterations; i++) { Console.WriteLine($"Applying directional blur {i + 1}/{iterations}..."); - finalImage = DirectionalBlur(finalImage, ImageMasks[0].Mask, radius, step, sigma); + finalImage = DirectionalBlur(finalImage, totalMask, radius, step, sigma); } - finalImage.SaveImage("final.png"); + finalImage.SaveImage("finalBlur.png"); Console.WriteLine("Done!"); } @@ -181,15 +199,14 @@ public static class Program { sw.Start(); kernels.Sdf(mask.Edges.ToArray(), (int)width, (int)height, out var temp); Console.WriteLine($"\nSDF Generation Time: {sw.Elapsed.TotalSeconds:N4}s ({width * height / sw.Elapsed.TotalSeconds:N0} pixels/s)"); - + sw.Restart(); var absMax = 0f; foreach (var pixel in temp) { if (pixel.X > absMax) absMax = pixel.X; } - - Parallel.For(0, width * height, parallelOptions, (i) => - { + + Parallel.For(0, width * height, parallelOptions, (i) => { //convert 1D index to 2D index var x = (int)(i % width); var y = (int)(i / width); @@ -198,8 +215,8 @@ public static class Program { sw.Stop(); Console.WriteLine( - $"SDF Normalization Time: {sw.Elapsed.TotalSeconds:N4}s ({width*height / sw.Elapsed.TotalSeconds:N0} pixels/s)"); - + $"SDF Normalization Time: {sw.Elapsed.TotalSeconds:N4}s ({width * height / sw.Elapsed.TotalSeconds:N0} pixels/s)"); + return new(temp); } diff --git a/SDFMapCreator/SdfKernels.Kernels.cs b/SDFMapCreator/SdfKernels.Kernels.cs index db33700..ff401e9 100644 --- a/SDFMapCreator/SdfKernels.Kernels.cs +++ b/SDFMapCreator/SdfKernels.Kernels.cs @@ -27,7 +27,7 @@ public partial class SdfKernels { var valueB = B[x, y]; var lumaA = valueA.X; var lumaB = valueB.X; - var r = lumaA > LUMA_THRESHOLD || lumaB > LUMA_THRESHOLD ? 1f : 0f; + var r = lumaB - lumaA > LUMA_THRESHOLD ? 1f : 0f; mask[x, y] = new(r, 0f, 0f); } @@ -84,6 +84,27 @@ public partial class SdfKernels { gradient[index] = new(a / (a + b)); } + static Vector3 SampleBilinear(ArrayView2D image, float x, float y) { + int width = image.IntExtent.X; + int height = image.IntExtent.Y; + + var x0 = (int)x; + var y0 = (int)y; + var x1 = x0 + 1; + var y1 = y0 + 1; + + if (x0 < 0 || x1 >= width || y0 < 0 || y1 >= height) return Vector3.Zero; + + var a = new Vector2(x - x0, y - y0); + var b = new Vector2(1f - a.X, 1f - a.Y); + + return Vector3.Lerp( + Vector3.Lerp(image[x0, y0], image[x1, y0], a.X), + Vector3.Lerp(image[x0, y1], image[x1, y1], a.X), + a.Y + ); + } + static void DirectionalBlurKernel(Index2D index, ArrayView2D image, ArrayView2D mask, @@ -101,13 +122,19 @@ public partial class SdfKernels { } var gradient = Vector2.Zero; - - for (var dx = -1; dx <= 1; dx++) { - for (var dy = -1; dy <= 1; dy++) { - if (x + dx < 0 || x + dx >= width || y + dy < 0 || y + dy >= height) continue; - gradient += new Vector2(dx, dy) * image[x + dx, y + dy].X; - } + + // calculate the gradient + for (int i = -1; i <= 1; i++) { + if (x + i < 0 || x + i >= width || y + i < 0 || y + i >= height) continue; + gradient.X += i * image[x + i, y].X; + gradient.Y += i * image[x, y + i].X; } + + /* + output[x, y] = new Vector3(float.Abs((gradient.X * 0.5f) + 0.5f), + float.Abs((gradient.Y * 0.5f) + 0.5f), 0.5f); + return; + */ if (gradient == Vector2.Zero) { output[x, y] = value; @@ -119,19 +146,19 @@ public partial class SdfKernels { // now we follow the direction line and sample the image for length; for (var l = -radius; l <= radius; l += step) { - var xOffset = (int)(gradient.X * l); - var yOffset = (int)(gradient.Y * l); + var xOffset = (gradient.X * l); + var yOffset = (gradient.Y * l); var xSample = x + xOffset; var ySample = y + yOffset; if (xSample < 0 || xSample >= width || ySample < 0 || ySample >= height) continue; - var sampleValue = image[xSample, ySample]; - var weight = MathF.Exp(-l * l / (2f * sigma * sigma)); + var sampleValue = SampleBilinear(image, xSample, ySample); + var weight = MathF.Exp(-(l * l) / (2f * sigma * sigma)); output[x, y] += sampleValue * weight; sum += weight; } - output[x, y] /= sum; + output[x, y] = output[x, y] / sum; } } \ No newline at end of file