Cleaned up main
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8056cd3f452fefb9834f05cdb275b762dd41f27b7766cd71174e78592dc495b_003FMonitor_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8056cd3f452fefb9834f05cdb275b762dd41f27b7766cd71174e78592dc495b_003FMonitor_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APixelTypeInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc3cfdca1fb93eb6df5e51a81da5df646adfab8b862fd1a07ee5d247b49c5179_003FPixelTypeInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APixelTypeInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc3cfdca1fb93eb6df5e51a81da5df646adfab8b862fd1a07ee5d247b49c5179_003FPixelTypeInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASafeFileHandle_002EUnix_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9cf5f68d759deefc91b9c48c5ac3dd27708bb7dc38d0c485661fff5ce15b82_003FSafeFileHandle_002EUnix_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASafeFileHandle_002EUnix_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9cf5f68d759deefc91b9c48c5ac3dd27708bb7dc38d0c485661fff5ce15b82_003FSafeFileHandle_002EUnix_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASafeFileHandle_002EWindows_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F261ea83c988816e3d8fe76b15b7ac6c10af64b8f9e739854f83c137c8ba9_003FSafeFileHandle_002EWindows_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2c8e7ca976f350cba9836d5565dac56b11e0b56656fa786460eb1395857a6fa_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003Fairon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F2c8e7ca976f350cba9836d5565dac56b11e0b56656fa786460eb1395857a6fa_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F6edafe13d8727aa238b865f5dc91dbc984b5abfbc60bece3744f6311c2c_003FVector3_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AVector3_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fmm00_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F6edafe13d8727aa238b865f5dc91dbc984b5abfbc60bece3744f6311c2c_003FVector3_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue"><AssemblyExplorer>
|
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue"><AssemblyExplorer>
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ public class Program {
|
|||||||
private const float MAX = 1f;
|
private const float MAX = 1f;
|
||||||
private const float MIN = 0f;
|
private const float MIN = 0f;
|
||||||
private static readonly int MAX_THREADS = Environment.ProcessorCount - 2;
|
private static readonly int MAX_THREADS = Environment.ProcessorCount - 2;
|
||||||
private const bool outputMasks = true;
|
private static bool debug = true;
|
||||||
private const bool outputSDFs = true;
|
|
||||||
private const bool outputGradients = true;
|
|
||||||
static readonly ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = MAX_THREADS };
|
static readonly ParallelOptions parallelOptions = new() { MaxDegreeOfParallelism = MAX_THREADS };
|
||||||
static List<Image> Images = new();
|
static List<Image> Images = new();
|
||||||
static List<MaskData> ImageMasks = new();
|
static List<MaskData> ImageMasks = new();
|
||||||
@@ -24,15 +22,18 @@ public class Program {
|
|||||||
|
|
||||||
public static void Main(string[] args) {
|
public static void Main(string[] args) {
|
||||||
Console.WriteLine("Reading images...");
|
Console.WriteLine("Reading images...");
|
||||||
|
|
||||||
/*
|
if(debug) {
|
||||||
|
if (!Directory.Exists("Debug")) Directory.CreateDirectory("Debug");
|
||||||
|
Console.WriteLine("Debug mode enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
var imagesPath = "images";
|
var imagesPath = "images";
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int 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");
|
||||||
@@ -41,59 +42,50 @@ public class Program {
|
|||||||
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
|
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
|
||||||
pixels = ImageUtil.LoadImage<Vector3>($"./spherefull.png");
|
pixels = ImageUtil.LoadImage<Vector3>($"./spherefull.png");
|
||||||
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
|
Images.Add(new(pixels, pixels.GetLength(0), pixels.GetLength(1)));
|
||||||
|
*/
|
||||||
|
|
||||||
//check if all the images in Images are the same resolution
|
//check if all the images in Images are the same resolution
|
||||||
if (Images.Select(img => (img.Width, img.Height)).Distinct().Count() > 1) {
|
if (Images.Select(img => (img.Width, img.Height)).Distinct().Count() > 1) {
|
||||||
Console.WriteLine("Error: Not all images have the same resolution.");
|
Console.WriteLine("Error: Not all images have the same resolution.");
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Images[i].Pixels.SaveImage($"./Sum{i}.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Creating masks...");
|
|
||||||
//for each image pair, create a mask
|
|
||||||
width = (uint)Images[0].Width;
|
width = (uint)Images[0].Width;
|
||||||
height = (uint)Images[0].Height;
|
height = (uint)Images[0].Height;
|
||||||
for (int i = 0; i < Images.Count; i++) {
|
|
||||||
ImageMasks.Add(new(SelfMask(Images[i].Pixels, width, height), Images[i], new()));
|
Console.WriteLine("Creating masks...");
|
||||||
if (i < Images.Count - 1) {
|
for (int i = 0; i < Images.Count; i++) { //for each image pair, create a mask
|
||||||
Console.WriteLine($"Creating mask {i}...");
|
var selfMask = SelfMask(Images[i].Pixels);
|
||||||
var mask = GetABMask(Images[i].Pixels, Images[i + 1].Pixels, width, height);
|
ImageMasks.Add(new(selfMask, Images[i], new()));
|
||||||
TransitionMasks.Add(new(mask, Images[i], Images[i + 1]));
|
if (debug) selfMask.SaveImage($"Debug/selfMask{i}.png");
|
||||||
}
|
if (i >= Images.Count - 1) continue;
|
||||||
|
ConsoleUpdateLine($"Creating mask {i}...");
|
||||||
|
var mask = GetABMask(Images[i].Pixels, Images[i + 1].Pixels);
|
||||||
|
TransitionMasks.Add(new(mask, Images[i], Images[i + 1]));
|
||||||
|
if (debug) mask.SaveImage($"Debug/mask{i}.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Edge detecting masks...");
|
|
||||||
//EdgeDetect all masks
|
//EdgeDetect all masks
|
||||||
foreach (var t in ImageMasks) EdgeDetect(t);
|
Console.WriteLine("\nEdge detecting masks...");
|
||||||
|
foreach (var mask in ImageMasks) {
|
||||||
if (outputMasks) {
|
ConsoleUpdateLine($"Edge detecting mask {ImageMasks.IndexOf(mask)}...");
|
||||||
Console.WriteLine("Writing masks...");
|
EdgeDetect(mask);
|
||||||
for (int i = 0; i < TransitionMasks.Count; i++) ImageMasks[i].Mask.SaveImage($"mask{i}.png");
|
|
||||||
}
|
}
|
||||||
|
if (debug) for (int i = 0; i < TransitionMasks.Count; i++) ImageMasks[i].Mask.SaveImage($"Debug/mask{i}.png");
|
||||||
|
|
||||||
Console.WriteLine("Creating SDFs...");
|
Console.WriteLine("Creating SDFs...");
|
||||||
for (var i = 0; i < ImageMasks.Count; i++) {
|
for (var i = 0; i < ImageMasks.Count; i++) {
|
||||||
var mask = ImageMasks[i];
|
var mask = ImageMasks[i];
|
||||||
SDFs.Add(SDF(mask));
|
SDFs.Add(SDF(mask));
|
||||||
if (outputSDFs) SDFs[i].SDF.SaveImage($"sdf{i}.png");
|
if (debug) SDFs[i].SDF.SaveImage($"Debug/sdf{i}.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Creating gradients...");
|
Console.WriteLine("Creating gradients...");
|
||||||
for (var i = 0; i < TransitionMasks.Count; i++) {
|
for (var i = 0; i < TransitionMasks.Count; i++) {
|
||||||
Console.WriteLine($"Generating gradient {i}...");
|
ConsoleUpdateLine($"Generating gradient {i}...");
|
||||||
var gradientData = Gradient(TransitionMasks[i], SDFs[i], SDFs[i + 1]);
|
var gradientData = Gradient(TransitionMasks[i], SDFs[i], SDFs[i + 1]);
|
||||||
Gradients.Add(gradientData);
|
Gradients.Add(gradientData);
|
||||||
if (outputGradients) gradientData.SaveImage($"gradient{i}.png");
|
if (debug) gradientData.SaveImage($"Debug/gradient{i}.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate final image
|
// generate final image
|
||||||
@@ -124,8 +116,6 @@ public class Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void EdgeDetect(MaskData maskData) {
|
private static void EdgeDetect(MaskData maskData) {
|
||||||
uint width = (uint)maskData.Image.Width;
|
|
||||||
uint height = (uint)maskData.Image.Height;
|
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
Console.WriteLine("Running edge detection...");
|
Console.WriteLine("Running edge detection...");
|
||||||
@@ -143,8 +133,6 @@ public class Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Vector3[,] Gradient(TransitionMaskData mask, SDFData sdfA, SDFData sdfB) {
|
static Vector3[,] Gradient(TransitionMaskData mask, SDFData sdfA, SDFData sdfB) {
|
||||||
uint width = (uint)mask.ImageA.Width;
|
|
||||||
uint height = (uint)mask.ImageA.Height;
|
|
||||||
int iterCount = 0;
|
int iterCount = 0;
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
@@ -179,43 +167,13 @@ public class Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SDFData SDF(MaskData mask) {
|
static SDFData SDF(MaskData mask) {
|
||||||
var width = (uint)mask.Mask.GetLength(0);
|
|
||||||
var height = (uint)mask.Mask.GetLength(1);
|
|
||||||
float AbsMax = MIN;
|
|
||||||
int iterCount = 0;
|
int iterCount = 0;
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
/*Parallel.For(0, width * height, parallelOptions, (i) =>
|
|
||||||
{
|
|
||||||
//convert 1D index to 2D index
|
|
||||||
var x = (int)(i % width);
|
|
||||||
var y = (int)(i / width);
|
|
||||||
Vector2 p = new(x / (float)width, y / (float)height); //get the pixel position as a Vector2
|
|
||||||
|
|
||||||
float minDist = MAX + 1; //initialize the minimum distance to the maximum possible value
|
|
||||||
|
|
||||||
//loop through all the pixels in the mask
|
|
||||||
foreach (var edge in mask.Edges) {
|
|
||||||
Vector2 edgeNorm = new(edge.X / (float)width, edge.Y / (float)height);
|
|
||||||
float dist = Vector2.DistanceSquared(p, edgeNorm);
|
|
||||||
if (dist < minDist) minDist = dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minDist > MAX)
|
|
||||||
minDist = MAX;
|
|
||||||
|
|
||||||
temp[x, y] = new(minDist);
|
|
||||||
if (minDist > AbsMax) AbsMax = minDist;
|
|
||||||
iterCount++;
|
|
||||||
if (iterCount % (width * height / 100) == 0) {
|
|
||||||
ConsoleUpdateLine(
|
|
||||||
$"Progress: {iterCount / (float)(width * height):P}% | {iterCount / (sw.Elapsed.TotalSeconds):N0} pixels/s");
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
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(
|
Console.WriteLine($"\nSDF Generation Time: {sw.Elapsed.TotalSeconds:N4}s ({iterCount / sw.Elapsed.TotalSeconds:N0} pixels/s)");
|
||||||
$"\nSDF Generation Time: {sw.Elapsed.TotalSeconds:N4}s ({iterCount / sw.Elapsed.TotalSeconds:N0} pixels/s)");
|
|
||||||
|
|
||||||
return new(temp);
|
return new(temp);
|
||||||
}
|
}
|
||||||
@@ -224,12 +182,12 @@ public class Program {
|
|||||||
private static float EuclideanDistance(Vector2 a, Vector2 b) =>
|
private static float EuclideanDistance(Vector2 a, Vector2 b) =>
|
||||||
MathF.Sqrt(MathF.Pow(a.X - b.X, 2) + MathF.Pow(a.Y - b.Y, 2));
|
MathF.Sqrt(MathF.Pow(a.X - b.X, 2) + MathF.Pow(a.Y - b.Y, 2));
|
||||||
|
|
||||||
static Vector3[,] GetABMask(Vector3[,] A, Vector3[,] B, uint resX, uint resY) {
|
static Vector3[,] GetABMask(Vector3[,] A, Vector3[,] B) {
|
||||||
kernels.ABMask(A, B, out var temp);
|
kernels.ABMask(A, B, out var temp);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3[,] SelfMask(Vector3[,] A, uint resX, uint resY) {
|
static Vector3[,] SelfMask(Vector3[,] A) {
|
||||||
kernels.SelfMask(A, out var temp);
|
kernels.SelfMask(A, out var temp);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ public partial class SdfKernels {
|
|||||||
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
Console.WriteLine($"{GetInfoString(accelerator)}");
|
Console.WriteLine($"{GetInfoString(accelerator)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Reading available accelerators (OpenCL only)...");
|
Console.WriteLine("Reading available accelerators (OpenCL only)...");
|
||||||
foreach (var device in gpuContext.GetCLDevices()) {
|
foreach (var device in gpuContext.GetCLDevices()) {
|
||||||
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
Console.WriteLine($"{GetInfoString(accelerator)}");
|
Console.WriteLine($"{GetInfoString(accelerator)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Reading available accelerators (CPU only)...");
|
Console.WriteLine("Reading available accelerators (CPU only)...");
|
||||||
foreach (var device in gpuContext.GetCPUDevices()) {
|
foreach (var device in gpuContext.GetCPUDevices()) {
|
||||||
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
using Accelerator accelerator = device.CreateAccelerator(gpuContext);
|
||||||
@@ -128,7 +130,7 @@ public partial class SdfKernels {
|
|||||||
sdf = buffer.GetAsArray2D();
|
sdf = buffer.GetAsArray2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Gradient(ref Vector3[,] mask, ref Vector3[,] sdfa, ref Vector3[,] sdfb, out Vector3[,] gradient) {
|
public void Gradient(Vector3[,] mask, Vector3[,] sdfa, Vector3[,] sdfb, out Vector3[,] gradient) {
|
||||||
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
|
var dev = gpuContext.GetPreferredDevice(preferCPU:false);
|
||||||
int width = mask.GetLength(0);
|
int width = mask.GetLength(0);
|
||||||
int height = mask.GetLength(1);
|
int height = mask.GetLength(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user