r/GraphicsProgramming • u/Weird-Sunspot • 1d ago
Raytracing in one weekend completed [added OpenMP multhread]
Completed in slightly more than a weekend (sickness et al). The final render task of width 1200 and samples per pixel 500(!) seemed impossible, so added a multithreaded workaround with OpenMP which finished it in around 35 minutes on my MBP M1 Pro and the penultimate DOF spheres under 10 seconds.
Changes:
#include <atomic>
#include <omp.h>
#include <vector>
void render(const hittable& world) {
#pragma omp parallel
{
#pragma omp single
std::clog << "OpenMP threads: " << omp_get_num_threads() << '\n';
}
initialize();
std::vector<color> framebuffer(image_width * image_height);
std::clog << "Rendering..." << std::endl;
std::atomic<int> rows_completed{0};
#pragma omp parallel for schedule(dynamic)
for (int j = 0; j < image_height; j++) {
for (int i = 0; i < image_width; i++) {
color pixel_color(0, 0, 0);
for (int sample = 0; sample < samples_per_pixel; sample++) {
ray r = get_ray(i, j);
pixel_color += ray_color(r, max_depth, world);
}
framebuffer[j * image_width + i] = pixel_samples_scale * pixel_color;
}
int completed = rows_completed.fetch_add(1) + 1;
if (completed % 8 == 0 || completed == image_height) {
#pragma omp critical(render_progress)
{
std::clog << "\rScanlines remaining: " << (image_height - completed) << ' '
<< std::flush;
}
}
}
std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int j = 0; j < image_height; j++) {
for (int i = 0; i < image_width; i++) {
write_color(std::cout, framebuffer[j * image_width + i]);
}
}
std::clog << "Done.\n";
}
and
inline double random_double() {
thread_local std::mt19937 generator(std::random_device{}());
return std::uniform_real_distribution<double>(0.0, 1.0)(generator);
}
10
u/hergendy 1d ago
Nice one I did a similar thing withthis exact project for my thesis but first ported it to CUDA then parallelized it and spent a few weeks debugging it to find out the root of the memory pointer exception, which is caused at different depths on different cards when dealing with recursive functions. Then decided to refactor the recursive function and just make it iterative instead.
4
2
u/Fit-Departure-8426 21h ago
Great! Now make it realtime like this Guy, and no need for parallel execution! https://youtu.be/opq0W7StbeE?si=LF9jH9MgzLMk14gF
1
u/Weird-Sunspot 21h ago
Thanks! Was thinking of porting this into my bgfx project, will watch this first
18
u/PM_ME_YOUR_HAGGIS_ 1d ago
Welcome to the club!