I did fix this bug by giving each thread its own random number generator to pass around between functions, but this caused the program to run a lot slower. The time taken to complete the rendering using multiple threads and the buggy RNG was about 45% of the original time. Now, after the fix, it takes about 92% of that time. This is something that I need to fix.
Another thing that can be improved in the program is how it is threaded. Currently it splits the image up into chunks and gets one thread to process each chunk - just like the parallel ray-tracer featured on my portfolio. However, this leaves threads sitting there doing nothing. I propose a new method to get all the threads to work at the same time throughout the rendering process.
I am not yet sure if the below code will work, but I think it gives the general idea of what I am trying to achieve:
int donePixels = 0;
int engagedThreads = 0;
int maxThreads = std::thread::hardware_concurrency();
int numPixels = width * height;
while(engagedThreads < maxThreads && donePixels < numPixels)
{
threads.push_back(thread(colourPixel, index)); // NB: I am still considering how to choose the index
engagedThreads++;
for(auto &t : threads)
{
t.join(); // I'm hoping this acts as a barrier
engagedThreads--;
donePixels++;
std::cout << donePixels * 100 / numPixels << "% done" << std::endl;
// Should I put a `break` here?
}
}
- It uses 10,000 samples per pixel
- It took 42 hours to render
- It uses boxes, spheres, a lighting material, noise, moving spheres, metal, glass, and textures.
- There is a volumetric fog around the whole scene
- There are not as many small spheres as in Peter Shirley's image
- The sphere that uses the Perlin noise (the centre sphere) does not seem to be correct, I will have to look into this as the noise was correct before but perhaps my changes to the randomness broke it.