Parallel noise processing

This commit is contained in:
Maximilian Giller 2023-01-29 15:48:17 +01:00
parent 9b07411ebd
commit a4d7ccc1a5
5 changed files with 43 additions and 13 deletions

View file

@ -2,9 +2,15 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <set> #include <set>
#include <thread>
#include "worleynoise.h" #include "worleynoise.h"
#include "common/vector3d.h" #include "common/vector3d.h"
void WorleyNoise::runWorleyNoiseInThread(int xOffset, int xSize, WorleyNoise *noise)
{
noise->renderNoiseThread(xOffset, xSize);
}
void WorleyNoise::generateNoise() void WorleyNoise::generateNoise()
{ {
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
@ -36,17 +42,21 @@ void WorleyNoise::generateNoise()
noiseMap.clear(); noiseMap.clear();
noiseMap.resize(size * size * size); 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<std::thread> threads;
for (int n = 0; n < nThreads; n++)
{ {
for (int y = 0; y < size; y++) threads.emplace_back(runWorleyNoiseInThread, n * threadSize, threadSize, this);
{
for (int z = 0; z < size; z++)
{
Vector3d point = Vector3d(x, y, z);
point /= (float) size;
setNoise(x, y, z, distanceToClosestPoint(point));
}
} }
renderNoiseThread(nThreads * threadSize, remaining);
// Rejoin the threads
for (int t = 0; t < nThreads; ++t)
{
threads[t].join();
} }
// Normalize getNoise map to [0, 1] // Normalize getNoise map to [0, 1]
@ -66,6 +76,22 @@ void WorleyNoise::generateNoise()
<< duration.count() << " seconds" << std::endl; << 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) WorleyNoise::WorleyNoise(int size, int numberOfPoints, unsigned int seed) : numberOfPoints(numberOfPoints), Noise(size)
{ {
// Init random // Init random

View file

@ -18,6 +18,8 @@ public:
*/ */
WorleyNoise(int size, int numberOfPoints, unsigned int seed = 0); WorleyNoise(int size, int numberOfPoints, unsigned int seed = 0);
void renderNoiseThread(int xOffset, int xSize);
protected: protected:
int numberOfPoints; int numberOfPoints;
std::vector<Vector3d> points; // 3D-Array, each cell represents a subcell. There are numberOfPoints^3 subcells. std::vector<Vector3d> points; // 3D-Array, each cell represents a subcell. There are numberOfPoints^3 subcells.
@ -32,6 +34,8 @@ protected:
void generateNoise(); void generateNoise();
std::vector<Vector3d> getSubcellPoints(Vector3d point); std::vector<Vector3d> getSubcellPoints(Vector3d point);
static void runWorleyNoiseInThread(int xOffset, int xSize, WorleyNoise *noise);
}; };

View file

@ -72,7 +72,7 @@ int main()
// Render the scene // Render the scene
SuperRenderer sr; SuperRenderer sr;
sr.setSuperSamplingFactor(1); sr.setSuperSamplingFactor(1);
sr.renderImage(scene, camera, 512, 512).save("result.png"); sr.renderImage(scene, camera, 256, 256).save("result.png");
return 0; return 0;
} }

View file

@ -69,7 +69,7 @@ bool CloudShader::isTransparent() const
} }
CloudShader::CloudShader(const CloudSettings &settings) : settings(settings), CloudShader::CloudShader(const CloudSettings &settings) : settings(settings),
cloudNoise(CloudNoise(NOISE_SIZE, settings.seed)) cloudNoise(CloudNoise(settings.noiseSize, settings.seed))
{ {
cloudNoise.invert = true; cloudNoise.invert = true;
} }

View file

@ -7,11 +7,11 @@
#include "primitive/primitive.h" #include "primitive/primitive.h"
#include "common/noise/worleynoise.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 float const TRANSMITTANCE_BREAK = 0.0001f; // If transmittance goes below this limit, the cloud is considered opaque
struct CloudSettings struct CloudSettings
{ {
int noiseSize = 256; // 64
unsigned int seed = 0; // 0 for random seed unsigned int seed = 0; // 0 for random seed
float densitySteps = .2f; // .2f float densitySteps = .2f; // .2f
float scale = 30; // 30 float scale = 30; // 30