Fixed directional blur

This commit is contained in:
mm00
2025-04-03 20:49:44 +02:00
parent dfa2cf3f31
commit 5cf8612699
2 changed files with 67 additions and 23 deletions

View File

@@ -29,12 +29,14 @@ public static class Program {
Console.WriteLine("Debug mode enabled."); Console.WriteLine("Debug mode enabled.");
} }
var imagesPath = "images"; var imagesPath = "images";
for (var i = 0; i < 8; i++) { for (var i = 0; i < 8; i++) {
var pixels = ImageUtil.LoadImage<Vector3>($"./{imagesPath}{Path.DirectorySeparatorChar}{i + 1:00}.png"); var pixels = ImageUtil.LoadImage<Vector3>($"./{imagesPath}{Path.DirectorySeparatorChar}{i + 1:00}.png");
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1))); Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
} }
/*
/*
var pixels = ImageUtil.LoadImage<Vector3>($"./sphereempty.png"); var pixels = ImageUtil.LoadImage<Vector3>($"./sphereempty.png");
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1))); Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
pixels = ImageUtil.LoadImage<Vector3>($"./spherehalf.png"); pixels = ImageUtil.LoadImage<Vector3>($"./spherehalf.png");
@@ -54,6 +56,18 @@ public static class Program {
width = (uint)Images[0].Width; width = (uint)Images[0].Width;
height = (uint)Images[0].Height; 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..."); Console.WriteLine("Creating masks...");
for (var i = 0; i < Images.Count; i++) { //for each image pair, create a mask for (var i = 0; i < Images.Count; i++) { //for each image pair, create a mask
var selfMask = SelfMask(Images[i].Pixels); var selfMask = SelfMask(Images[i].Pixels);
@@ -113,18 +127,22 @@ public static class Program {
} }
currStep += stepIncrement; currStep += stepIncrement;
} }
finalImage.SaveImage("Debug/Final.png");
// apply directional blur // apply directional blur
var iterations = 10; var iterations = 1;
var radius = 3f; var radius = 100f;
var step = .5f; var step = .5f;
var sigma = 1f; var sigma = 1f;
var totalMask = SelfMask(Images[^1].Pixels);
totalMask.SaveImage("Debug/TotalMask.png");
for (var i = 0; i < iterations; i++) { for (var i = 0; i < iterations; i++) {
Console.WriteLine($"Applying directional blur {i + 1}/{iterations}..."); 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!"); Console.WriteLine("Done!");
} }
@@ -181,15 +199,14 @@ public static class Program {
sw.Start(); sw.Start();
kernels.Sdf(mask.Edges.ToArray(), (int)width, (int)height, out var temp); 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)"); Console.WriteLine($"\nSDF Generation Time: {sw.Elapsed.TotalSeconds:N4}s ({width * height / sw.Elapsed.TotalSeconds:N0} pixels/s)");
sw.Restart(); sw.Restart();
var absMax = 0f; var absMax = 0f;
foreach (var pixel in temp) { foreach (var pixel in temp) {
if (pixel.X > absMax) absMax = pixel.X; 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 //convert 1D index to 2D index
var x = (int)(i % width); var x = (int)(i % width);
var y = (int)(i / width); var y = (int)(i / width);
@@ -198,8 +215,8 @@ public static class Program {
sw.Stop(); sw.Stop();
Console.WriteLine( 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); return new(temp);
} }

View File

@@ -27,7 +27,7 @@ public partial class SdfKernels {
var valueB = B[x, y]; var valueB = B[x, y];
var lumaA = valueA.X; var lumaA = valueA.X;
var lumaB = valueB.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); mask[x, y] = new(r, 0f, 0f);
} }
@@ -84,6 +84,27 @@ public partial class SdfKernels {
gradient[index] = new(a / (a + b)); gradient[index] = new(a / (a + b));
} }
static Vector3 SampleBilinear(ArrayView2D<Vector3, Stride2D.DenseX> 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, static void DirectionalBlurKernel(Index2D index,
ArrayView2D<Vector3, Stride2D.DenseX> image, ArrayView2D<Vector3, Stride2D.DenseX> image,
ArrayView2D<Vector3, Stride2D.DenseX> mask, ArrayView2D<Vector3, Stride2D.DenseX> mask,
@@ -101,13 +122,19 @@ public partial class SdfKernels {
} }
var gradient = Vector2.Zero; var gradient = Vector2.Zero;
for (var dx = -1; dx <= 1; dx++) { // calculate the gradient
for (var dy = -1; dy <= 1; dy++) { for (int i = -1; i <= 1; i++) {
if (x + dx < 0 || x + dx >= width || y + dy < 0 || y + dy >= height) continue; if (x + i < 0 || x + i >= width || y + i < 0 || y + i >= height) continue;
gradient += new Vector2(dx, dy) * image[x + dx, y + dy].X; 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) { if (gradient == Vector2.Zero) {
output[x, y] = value; output[x, y] = value;
@@ -119,19 +146,19 @@ public partial class SdfKernels {
// now we follow the direction line and sample the image for length; // now we follow the direction line and sample the image for length;
for (var l = -radius; l <= radius; l += step) { for (var l = -radius; l <= radius; l += step) {
var xOffset = (int)(gradient.X * l); var xOffset = (gradient.X * l);
var yOffset = (int)(gradient.Y * l); var yOffset = (gradient.Y * l);
var xSample = x + xOffset; var xSample = x + xOffset;
var ySample = y + yOffset; var ySample = y + yOffset;
if (xSample < 0 || xSample >= width || ySample < 0 || ySample >= height) continue; if (xSample < 0 || xSample >= width || ySample < 0 || ySample >= height) continue;
var sampleValue = image[xSample, ySample]; var sampleValue = SampleBilinear(image, xSample, ySample);
var weight = MathF.Exp(-l * l / (2f * sigma * sigma)); var weight = MathF.Exp(-(l * l) / (2f * sigma * sigma));
output[x, y] += sampleValue * weight; output[x, y] += sampleValue * weight;
sum += weight; sum += weight;
} }
output[x, y] /= sum; output[x, y] = output[x, y] / sum;
} }
} }