From cc78c886c82ac74deebeaccb7a3c1eca64031a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?arvid=20schr=C3=B6der?= Date: Tue, 13 Dec 2022 02:47:01 +0100 Subject: [PATCH] Added superrender --- renderer/superrenderer.cpp | 110 +++++++++++++++++++++++++++++++++++++ renderer/superrenderer.h | 33 +++++++++++ 2 files changed, 143 insertions(+) create mode 100644 renderer/superrenderer.cpp create mode 100644 renderer/superrenderer.h diff --git a/renderer/superrenderer.cpp b/renderer/superrenderer.cpp new file mode 100644 index 0000000..6c17403 --- /dev/null +++ b/renderer/superrenderer.cpp @@ -0,0 +1,110 @@ +// +// Created by arvids on 13.12.22. +// + +#include "superrenderer.h" +#include "common/ray.h" +#include +#include +#include +#include +#include "camera/camera.h" +#include "scene/scene.h" + +void SuperRenderer::renderThread(const Scene *scene, Camera const *camera, Texture *image, int width, int widthStep, + int widthOffset, int height, int heightStep, int heightOffset, std::atomic *k, + int const stepSize, int superSamplingFactor) { + float const aspectRatio = static_cast(height) / width; + for (int y = heightOffset; y < height; y += heightStep) { + for (int x = widthOffset; x < width; x += widthStep) { + Color fragmentColor = {}; + fragmentColor = calcSuperColor(scene, camera, width, height, superSamplingFactor, aspectRatio, y, x, + fragmentColor); + fragmentColor /= static_cast(superSamplingFactor * superSamplingFactor); + image->setPixelAt(x, y, clamped(fragmentColor)); + // Super hacky progress bar! + if (++*k % stepSize == 0) { + std::cout << "=" << std::flush; + } + } + } +} + +Color & +SuperRenderer::calcSuperColor(const Scene *scene, const Camera *camera, int width, int height, int superSamplingFactor, + const float aspectRatio, int y, int x, Color &fragmentColor) { + for (int x1 = 0; x1 < superSamplingFactor; x1++) { + for (int y1 = 0; y1 < superSamplingFactor; y1++) { + float offsetX = (-0.5f + static_cast(x1) / static_cast(superSamplingFactor - 1)); + float offsetY = (-0.5f + static_cast(y1) / static_cast(superSamplingFactor - 1)); + + Ray ray = camera->createRay(((static_cast(x) + offsetX) / static_cast(width) * 2.0f - 1), + -((static_cast(y) + offsetY) / static_cast(height) * 2.0f - 1) * aspectRatio); + fragmentColor += scene->traceRay(ray); + } + } + return fragmentColor; +} + +Texture SuperRenderer::renderImage(Scene const &scene, Camera const &camera, int width, int height) { + Texture image(width, height); + + // Setup timer + std::chrono::steady_clock::time_point start, stop; + + // Reset Ray counting + Ray::resetRayCount(); + + // Super-hacky progress bar! + std::cout << "(SuperRenderer): Begin rendering..." << std::endl; + std::cout << "| 0%"; + int const barSize = 50; + int const stepSize = (width * height) / barSize; + for (int i = 0; i < barSize - 3 - 5; ++i) + std::cout << " "; + std::cout << "100% |" << std::endl << "|"; + std::atomic k(0); + + /* Start timer */ start = std::chrono::steady_clock::now(); + + // Spawn a thread for every logical processor -1, calling the renderThread function + int const nThreads = std::thread::hardware_concurrency(); + std::vector threads; + for (int t = 0; t < nThreads - 1; ++t) { + threads.emplace_back(renderThread, &scene, &camera, &image, width, nThreads, t, height, 1, 0, &k, stepSize, + this->superSamplingFactor); + } + + // Call the renderThread function yourself + renderThread(&scene, &camera, &image, width, nThreads, nThreads - 1, height, 1, 0, &k, stepSize, + this->superSamplingFactor); + + // Rejoin the threads + for (int t = 0; t < nThreads - 1; ++t) { + threads[t].join(); + } + + // Stop timer + stop = std::chrono::steady_clock::now(); + + std::cout << "| Done!" << std::endl; + + // Calculate the Time taken in seconds + double seconds = std::chrono::duration_cast>(stop - start).count(); + + std::cout << "Time: " << seconds << "s" << std::endl; + + // Get the number of seconds per ray + int rays = Ray::getRayCount(); + + std::cout << "Paths: " << rays << std::endl; + std::cout << "Paths per second: " << std::fixed << std::setprecision(0) << rays / seconds << std::endl; + + + return image; +} + + +void SuperRenderer::setSuperSamplingFactor(int superSamplingFactor) { + SuperRenderer::superSamplingFactor = superSamplingFactor; +} diff --git a/renderer/superrenderer.h b/renderer/superrenderer.h new file mode 100644 index 0000000..92c88c1 --- /dev/null +++ b/renderer/superrenderer.h @@ -0,0 +1,33 @@ +// +// Created by arvids on 13.12.22. +// + +#ifndef CG1_TRACER_SUPERRENDERER_H +#define CG1_TRACER_SUPERRENDERER_H + +#include "renderer.h" +#include +#include + +class SuperRenderer : public Renderer { +public: + static void + renderThread(const Scene *scene, Camera const *camera, Texture *image, int width, int widthStep, + int widthOffset, int height, int heightStep, int heightOffset, std::atomic *k, + int const stepSize, int superSamplingFactor); + + Texture renderImage(const Scene &scene, const Camera &camera, int width, int height) override; + void setSuperSamplingFactor(int superSamplingFactor); + +private: +private: + + int superSamplingFactor; + + static Color & + calcSuperColor(const Scene *scene, const Camera *camera, int width, int height, int superSamplingFactor, + const float aspectRatio, int y, int x, Color &fragmentColor); +}; + + +#endif //CG1_TRACER_SUPERRENDERER_H