Added directional blur

This commit is contained in:
mm00
2025-04-03 18:48:21 +02:00
parent db54b80b5a
commit 2d1368a908
3 changed files with 114 additions and 0 deletions

View File

@@ -119,6 +119,18 @@ public class Program {
}
currStep += stepIncrement;
}
// apply directional blur
var iterations = 10;
var radius = 3f;
var step = .5f;
var sigma = 1f;
for (int i = 0; i < iterations; i++)
{
Console.WriteLine($"Applying directional blur {i + 1}/{iterations}...");
finalImage = DirectionalBlur(finalImage, ImageMasks[0].Mask, radius, step, sigma);
}
finalImage.SaveImage("final.png");
Console.WriteLine("Done!");
}
@@ -219,6 +231,22 @@ public class Program {
return new(temp);
}
static Vector3[,] DirectionalBlur(Vector3[,] image, Vector3[,] mask, float radius = 3f, float step = .5f, float sigma = 1f) {
var width = (uint)image.GetLength(0);
var height = (uint)image.GetLength(1);
var output = new Vector3[width, height];
var sw = new Stopwatch();
sw.Start();
kernels.DirectionalBlur(image, mask, out var temp, radius, step, sigma);
Console.WriteLine(
$"Directional Blur Time: {sw.Elapsed.TotalSeconds:N4}s ({width * height / sw.Elapsed.TotalSeconds:N0} pixels/s)");
return temp;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float EuclideanDistance(Vector2 a, Vector2 b) =>

View File

@@ -79,5 +79,61 @@ public partial class SdfKernels {
if(mask[index].X == 0f || mask[index].Y == 0f) return;
float a = sdfa[index].X; float b = sdfb[index].X;
gradient[index] = new (a / (a + b));
private static void DirectionalBlurKernel(Index2D index,
ArrayView2D<Vector3, Stride2D.DenseX> image,
ArrayView2D<Vector3, Stride2D.DenseX> mask,
ArrayView2D<Vector3, Stride2D.DenseX> output,
float radius, float step, float sigma,
int width, int height
)
{
int x = index.X;
int y = index.Y;
Vector3 value = image[x, y];
Vector3 maskValue = mask[x, y];
if (maskValue.X == 0f)
{
output[x, y] = value;
return;
}
var gradient = Vector2.Zero;
for (int dx = -1; dx <= 1; dx++)
{
for (int 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;
}
}
if (gradient == Vector2.Zero)
{
output[x, y] = value;
return;
}
gradient = Vector2.Normalize(gradient);
float sum = 0;
// now we follow the direction line and sample the image for length;
for (float l = -radius; l <= radius; l += step)
{
int xOffset = (int)(gradient.X * l);
int yOffset = (int)(gradient.Y * l);
int xSample = x + xOffset;
int ySample = y + yOffset;
if (xSample < 0 || xSample >= width || ySample < 0 || ySample >= height) continue;
Vector3 sampleValue = image[xSample, ySample];
float weight = MathF.Exp(-l * l / (2f * sigma * sigma));
output[x, y] += sampleValue * weight;
sum += weight;
}
output[x, y] /= sum;
}
}

View File

@@ -5,6 +5,7 @@ using ILGPU.Runtime;
using ILGPU.Runtime.CPU;
using ILGPU.Runtime.Cuda;
using ILGPU.Runtime.OpenCL;
using ILGPU.Algorithms;
namespace SDFMapCreator;
@@ -18,6 +19,7 @@ public partial class SdfKernels {
.Cuda()
.CPU()
.Math(MathMode.Fast32BitOnly)
.EnableAlgorithms()
);
Console.WriteLine("Reading available accelerators (CUDA only)...");
@@ -157,6 +159,34 @@ public partial class SdfKernels {
accelerator.Synchronize();
gradient = bufferMask.GetAsArray2D();
public void DirectionalBlur(Vector3[,] image, Vector3[,] mask, out Vector3[,] output, float radius = 3f, float step = .5f, float sigma = 1f) {
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
int width = image.GetLength(0);
int height = image.GetLength(1);
output = new Vector3[width, height];
using Accelerator accelerator = dev.CreateAccelerator(gpuContext);
using var imageBuffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
imageBuffer.CopyFromCPU(image);
using var maskBuffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
maskBuffer.CopyFromCPU(mask);
using var outputBuffer = accelerator.Allocate2DDenseX<Vector3>(new (width, height));
var blurKernel = accelerator.LoadAutoGroupedStreamKernel<Index2D,
ArrayView2D<Vector3, Stride2D.DenseX>,
ArrayView2D<Vector3, Stride2D.DenseX>,
ArrayView2D<Vector3, Stride2D.DenseX>,
float, float, float, int, int>(DirectionalBlurKernel);
blurKernel(new (width, height), imageBuffer.View, maskBuffer.View, outputBuffer.View,
radius, step, sigma, width, height);
accelerator.Synchronize();
output = outputBuffer.GetAsArray2D();
}
private static string GetInfoString(Accelerator a)