From a4d7ccc1a559ace02900af902b14da68ea6e1492 Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Sun, 29 Jan 2023 15:48:17 +0100 Subject: [PATCH] Parallel noise processing --- common/noise/worleynoise.cpp | 46 ++++++++++++++++++++++++++++-------- common/noise/worleynoise.h | 4 ++++ fancy1.cpp | 2 +- shader/cloudshader.cpp | 2 +- shader/cloudshader.h | 2 +- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/common/noise/worleynoise.cpp b/common/noise/worleynoise.cpp index 3d65749..d6ce4a9 100644 --- a/common/noise/worleynoise.cpp +++ b/common/noise/worleynoise.cpp @@ -2,9 +2,15 @@ #include #include #include +#include #include "worleynoise.h" #include "common/vector3d.h" +void WorleyNoise::runWorleyNoiseInThread(int xOffset, int xSize, WorleyNoise *noise) +{ + noise->renderNoiseThread(xOffset, xSize); +} + void WorleyNoise::generateNoise() { auto start = std::chrono::high_resolution_clock::now(); @@ -36,17 +42,21 @@ void WorleyNoise::generateNoise() noiseMap.clear(); noiseMap.resize(size * size * size); - for (int x = 0; x < size; x++) + int const nThreads = (int) std::thread::hardware_concurrency() - 1; + int threadSize = std::floor((float) size / (float) nThreads); + int remaining = size - nThreads * threadSize; + std::vector threads; + for (int n = 0; n < nThreads; n++) { - for (int y = 0; y < size; y++) - { - for (int z = 0; z < size; z++) - { - Vector3d point = Vector3d(x, y, z); - point /= (float) size; - setNoise(x, y, z, distanceToClosestPoint(point)); - } - } + threads.emplace_back(runWorleyNoiseInThread, n * threadSize, threadSize, this); + } + + renderNoiseThread(nThreads * threadSize, remaining); + + // Rejoin the threads + for (int t = 0; t < nThreads; ++t) + { + threads[t].join(); } // Normalize getNoise map to [0, 1] @@ -66,6 +76,22 @@ void WorleyNoise::generateNoise() << duration.count() << " seconds" << std::endl; } +void WorleyNoise::renderNoiseThread(int xOffset, int xSize) +{ + for (int x = 0; x < xSize; x++) + { + for (int y = 0; y < size; y++) + { + for (int z = 0; z < size; z++) + { + Vector3d point = Vector3d(x, y, z); + point /= (float) size; + setNoise(xOffset + x, y, z, distanceToClosestPoint(point)); + } + } + } +} + WorleyNoise::WorleyNoise(int size, int numberOfPoints, unsigned int seed) : numberOfPoints(numberOfPoints), Noise(size) { // Init random diff --git a/common/noise/worleynoise.h b/common/noise/worleynoise.h index 3a37390..4994e5e 100644 --- a/common/noise/worleynoise.h +++ b/common/noise/worleynoise.h @@ -18,6 +18,8 @@ public: */ WorleyNoise(int size, int numberOfPoints, unsigned int seed = 0); + void renderNoiseThread(int xOffset, int xSize); + protected: int numberOfPoints; std::vector points; // 3D-Array, each cell represents a subcell. There are numberOfPoints^3 subcells. @@ -32,6 +34,8 @@ protected: void generateNoise(); std::vector getSubcellPoints(Vector3d point); + + static void runWorleyNoiseInThread(int xOffset, int xSize, WorleyNoise *noise); }; diff --git a/fancy1.cpp b/fancy1.cpp index f55e46e..4c0cad3 100644 --- a/fancy1.cpp +++ b/fancy1.cpp @@ -72,7 +72,7 @@ int main() // Render the scene SuperRenderer sr; sr.setSuperSamplingFactor(1); - sr.renderImage(scene, camera, 512, 512).save("result.png"); + sr.renderImage(scene, camera, 256, 256).save("result.png"); return 0; } diff --git a/shader/cloudshader.cpp b/shader/cloudshader.cpp index dd8a11a..6358d1d 100644 --- a/shader/cloudshader.cpp +++ b/shader/cloudshader.cpp @@ -69,7 +69,7 @@ bool CloudShader::isTransparent() const } CloudShader::CloudShader(const CloudSettings &settings) : settings(settings), - cloudNoise(CloudNoise(NOISE_SIZE, settings.seed)) + cloudNoise(CloudNoise(settings.noiseSize, settings.seed)) { cloudNoise.invert = true; } diff --git a/shader/cloudshader.h b/shader/cloudshader.h index a85d394..edc78d1 100644 --- a/shader/cloudshader.h +++ b/shader/cloudshader.h @@ -7,11 +7,11 @@ #include "primitive/primitive.h" #include "common/noise/worleynoise.h" -int const NOISE_SIZE = 64; float const TRANSMITTANCE_BREAK = 0.0001f; // If transmittance goes below this limit, the cloud is considered opaque struct CloudSettings { + int noiseSize = 256; // 64 unsigned int seed = 0; // 0 for random seed float densitySteps = .2f; // .2f float scale = 30; // 30