]> git.seodisparate.com - blue_noise_generation/commitdiff
WIP Attempt to fix resulting blue-noise
authorStephen Seo <seo.disparate@gmail.com>
Wed, 10 Nov 2021 09:12:04 +0000 (18:12 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 10 Nov 2021 09:12:04 +0000 (18:12 +0900)
src/blue_noise.cl
src/blue_noise.cpp
src/blue_noise.hpp
src/main.cpp

index 6d0611c833537f51f4208516225bd232efa42338..f39228edb386f61e253933a9f1b89a50754d6673 100644 (file)
@@ -22,10 +22,11 @@ __kernel void do_filter(
     if(i < 0 || i >= width * height) {
         return;
     }
+
     int x = i % width;
     int y = i / width;
 
-    float sum = 0.0f;
+    float sum = 0.0F;
     for(int q = 0; q < filter_size; ++q) {
         int q_prime = height - filter_size / 2 + y + q;
         for(int p = 0; p < filter_size; ++p) {
index f807a43349ba56243ff0b7dc0fbe69613d9cfacc..ba2a959e8fe38dd78193b5e522e3325b60cb85d8 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <CL/opencl.h>
 
+#include "image.hpp"
+
 #ifndef NDEBUG
 # include <cstdio>
 #endif
@@ -245,7 +247,7 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
 }
 
 std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
-        int width, int height, int filter_size, cl_context context, cl_device_id device, cl_program program) {
+        const int width, const int height, const int filter_size, cl_context context, cl_device_id device, cl_program program) {
     cl_int err;
     cl_kernel kernel;
     cl_command_queue queue;
@@ -262,10 +264,10 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
     queue = clCreateCommandQueueWithProperties(context, device, nullptr, &err);
 
     d_filter_out = clCreateBuffer(context, CL_MEM_WRITE_ONLY, count * sizeof(float), nullptr, nullptr);
-    d_precomputed = clCreateBuffer(context, CL_MEM_READ_ONLY, filter_size * filter_size * sizeof(float), nullptr, nullptr);
+    d_precomputed = clCreateBuffer(context, CL_MEM_READ_ONLY, precomputed.size() * sizeof(float), nullptr, nullptr);
     d_pbp = clCreateBuffer(context, CL_MEM_READ_ONLY, count * sizeof(int), nullptr, nullptr);
 
-    err = clEnqueueWriteBuffer(queue, d_precomputed, CL_TRUE, 0, filter_size * filter_size * sizeof(float), &precomputed[0], 0, nullptr, nullptr);
+    err = clEnqueueWriteBuffer(queue, d_precomputed, CL_TRUE, 0, precomputed.size() * sizeof(float), &precomputed[0], 0, nullptr, nullptr);
     if(err != CL_SUCCESS) {
         std::cerr << "OpenCL: Failed to write to d_precomputed buffer\n";
         clReleaseMemObject(d_pbp);
@@ -356,14 +358,27 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
         clReleaseCommandQueue(queue);
         return {};
     }
-    if(clSetKernelArg(kernel, 5, sizeof(int), &filter_size) != CL_SUCCESS) {
-        std::cerr << "OpenCL: Failed to set kernel arg 4\n";
-        clReleaseKernel(kernel);
-        clReleaseMemObject(d_pbp);
-        clReleaseMemObject(d_precomputed);
-        clReleaseMemObject(d_filter_out);
-        clReleaseCommandQueue(queue);
-        return {};
+    if (filter_size % 2 == 0) {
+        int filter_size_odd = filter_size + 1;
+        if(clSetKernelArg(kernel, 5, sizeof(int), &filter_size_odd) != CL_SUCCESS) {
+            std::cerr << "OpenCL: Failed to set kernel arg 4\n";
+            clReleaseKernel(kernel);
+            clReleaseMemObject(d_pbp);
+            clReleaseMemObject(d_precomputed);
+            clReleaseMemObject(d_filter_out);
+            clReleaseCommandQueue(queue);
+            return {};
+        }
+    } else {
+        if(clSetKernelArg(kernel, 5, sizeof(int), &filter_size) != CL_SUCCESS) {
+            std::cerr << "OpenCL: Failed to set kernel arg 4\n";
+            clReleaseKernel(kernel);
+            clReleaseMemObject(d_pbp);
+            clReleaseMemObject(d_precomputed);
+            clReleaseMemObject(d_filter_out);
+            clReleaseCommandQueue(queue);
+            return {};
+        }
     }
 
     if(clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(std::size_t), &local_size, nullptr) != CL_SUCCESS) {
@@ -502,6 +517,8 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
         }
 
         if(iterations % 100 == 0) {
+            std::cout << "max was " << max << ", second_min is " << second_min
+                << std::endl;
             // generate blue_noise image from pbp
             FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
             fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
@@ -539,7 +556,7 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
 
     std::cout << "Generating dither_array...\n";
     std::unordered_set<unsigned int> set;
-    std::vector<unsigned int> dither_array(count);
+    std::vector<unsigned int> dither_array(count, 0);
     int min, max;
     {
         std::vector<bool> pbp_copy(pbp);
@@ -557,6 +574,10 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
             }
         }
         pbp = pbp_copy;
+#ifndef NDEBUG
+        image::Bl min_pixels = internal::rangeToBl(dither_array, width);
+        min_pixels.writeToFile(image::file_type::PNG, true, "da_min_pixels.png");
+#endif
     }
     std::cout << "\nRanking remainder of first half of pixels...\n";
     for (unsigned int i = pixel_count; i < (unsigned int)((count + 1) / 2); ++i) {
@@ -573,6 +594,8 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
     }
 #ifndef NDEBUG
     {
+        image::Bl min_pixels = internal::rangeToBl(dither_array, width);
+        min_pixels.writeToFile(image::file_type::PNG, true, "da_mid_pixels.png");
         get_filter();
         internal::write_filter(filter, width, "filter_mid.pgm");
         image::Bl pbp_image = toBl(pbp, width);
index d61668aa1c39e3e9f8fdda29fcbaa83aa84615fa..dad166907b6bd4c901f185cc1a13ca34a353f13b 100644 (file)
@@ -30,7 +30,7 @@ image::Bl blue_noise(int width, int height, int threads = 1, bool use_opencl = t
 namespace internal {
     std::vector<unsigned int> blue_noise_impl(int width, int height, int threads = 1);
     std::vector<unsigned int> blue_noise_cl_impl(
-        int width, int height, int filter_size,
+        const int width, const int height, const int filter_size,
         cl_context context, cl_device_id device, cl_program program);
 
     inline std::vector<bool> random_noise(int size, int subsize) {
@@ -69,13 +69,16 @@ namespace internal {
 
     inline std::vector<float> precompute_gaussian(int size) {
         std::vector<float> precomputed;
+        if (size % 2 == 0) {
+            ++size;
+        }
         precomputed.reserve(size * size);
 
         for(int i = 0; i < size * size; ++i) {
             auto xy = utility::oneToTwo(i, size);
             precomputed.push_back(gaussian(
-                (float)xy.first - (float)size / 2.0F + 0.5F,
-                (float)xy.second - (float)size / 2.0F + 0.5F));
+                xy.first - (size / 2),
+                xy.second - (size / 2)));
         }
 
         return precomputed;
@@ -230,6 +233,7 @@ namespace internal {
             }
         }
         if (count * 2 >= pbp.size()) {
+            //std::cout << "MINMAX flip\n"; // DEBUG
             for (unsigned int i = 0; i < pbp.size(); ++i) {
                 pbp[i] = !pbp[i];
             }
index 6814b9b779af449180890efcd405cdb1d8fb30a3..d973f94878a1e812a0cee3ba3e168dd13ec59bd4 100644 (file)
@@ -5,7 +5,7 @@
 int main(int argc, char **argv) {
 //#ifndef NDEBUG
     std::cout << "Trying blue_noise..." << std::endl;
-    image::Bl bl = dither::blue_noise(32, 32, 15, true);
+    image::Bl bl = dither::blue_noise(64, 64, 15, true);
     bl.writeToFile(image::file_type::PNG, true, "blueNoiseOut.png");
 //#endif