From 9a8d6bcccd337de7ba349f4216cfee28e30a6608 Mon Sep 17 00:00:00 2001 From: "m.gaedke" Date: Tue, 24 Jan 2023 13:32:19 +0100 Subject: [PATCH 1/4] Bloom shader as post-processing --- CMakeLists.txt | 3 +- common/texture.cpp | 59 +++++++++++++++++++++++++++++++++ common/texture.h | 48 +++++++++++++++++---------- post-processing/bloomshader.cpp | 44 ++++++++++++++++++++++++ post-processing/bloomshader.h | 27 +++++++++++++++ renderer/simplerenderer.cpp | 7 ++++ 6 files changed, 169 insertions(+), 19 deletions(-) create mode 100644 post-processing/bloomshader.cpp create mode 100644 post-processing/bloomshader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 836320d..5ed9dac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,8 @@ file(GLOB shader_src "shader/*.cpp") # The tracey library add_library(tracey STATIC ${common_src} ${noise_src} ${camera_src} ${light_src} - ${primitive_src} ${renderer_src} ${scene_src} ${shader_src} light/ambientlight.cpp light/ambientlight.h light/spotlight.cpp light/spotlight.h) + ${primitive_src} ${renderer_src} ${scene_src} ${shader_src} light/ambientlight.cpp light/ambientlight.h + light/spotlight.cpp light/spotlight.h post-processing/bloomshader.cpp post-processing/bloomshader.h) if(NOT WIN32) target_link_libraries(tracey ${CMAKE_THREAD_LIBS_INIT} ${X11_LIBRARIES}) endif() diff --git a/common/texture.cpp b/common/texture.cpp index f7f0b70..6f7e845 100644 --- a/common/texture.cpp +++ b/common/texture.cpp @@ -83,3 +83,62 @@ Color Texture::color(float u, float v, bool interpolate) const { Color Texture::color(Vector2d const &surfacePosition, bool interpolate) const { return color(surfacePosition.u, surfacePosition.v, interpolate); } + +void Texture::gaussianBlur(int kernelSize, float sigma) { + CImg kernel = computeGaussianKernel(kernelSize, sigma); + image_ = convolution(image_, kernel); +} + +// Function to compute Gaussian kernel +CImg Texture::computeGaussianKernel(int kernelSize, float sigma) { + // Create kernel + CImg kernel(kernelSize, kernelSize, 1, 1); + + // Compute Gaussian kernel + float sum = 0.0f; + int i, j; + for (i = 0; i < kernelSize; i++) { + for (j = 0; j < kernelSize; j++) { + kernel(i, j) = exp(-0.5f * (pow((i - kernelSize / 2.f) / sigma, 2.f) + + pow((j - kernelSize / 2.f) / sigma, 2.f))) / (2 * M_PI * sigma * sigma); + sum += kernel(i, j); + } + } + + // Normalize kernel + kernel /= sum; + + return kernel; +} + +// Function to perform convolution +CImg Texture::convolution(CImg &img, CImg &kernel) { + int kernelSize = kernel.width(); + int imgRows = img.height(); + int imgCols = img.width(); + CImg result(imgCols, imgRows, 1, 3); + float sum; + int i, j, m, n; + int kernelRadius = kernelSize / 2; + + // Perform convolution + cimg_forXYC(img, i, j, c) { + sum = 0; + cimg_forY(kernel, m) { + cimg_forX(kernel, n) { + int x = i + n - kernelRadius; + int y = j + m - kernelRadius; + if(x >= 0 && x < imgCols && y >= 0 && y < imgRows){ + sum += img(x, y, 0, c) * kernel(n, m); + } + + } + } + result(i, j, 0, c) = sum; + } + return result; +} + +void Texture::scaleBrightness(float scale) { + image_ *= scale; +} diff --git a/common/texture.h b/common/texture.h index 3350a1c..184a754 100644 --- a/common/texture.h +++ b/common/texture.h @@ -9,30 +9,42 @@ using namespace cimg_library; class Texture { public: - // Constructor - Texture(int width, int height); - Texture(char const *fileName); + // Constructor + Texture(int width, int height); + Texture(char const *fileName); - // Image functions - inline void resize(int width, int height) { this->image_.resize(width, height, 1, 3); } - bool load(char const *fileName); - bool save(char const *fileName) const; + // Image functions + inline void resize(int width, int height) { this->image_.resize(width, height, 1, 3); } + bool load(char const *fileName); + bool save(char const *fileName) const; - // Get - inline bool isNull() const { return this->image_.is_empty(); } - inline int width() const { return this->image_.width(); } - inline int height() const { return this->image_.height(); } - Color getPixelAt(int x, int y) const; + // Gaussian blur function + void gaussianBlur(int kernelSize, float sigma); - // Set - void setPixelAt(int x, int y, Color const &color); + // Scale function + void scaleBrightness(float scale); - // Color functions - Color color(float u, float v, bool interpolate = true) const; - Color color(Vector2d const &surfacePosition, bool interpolate = true) const; + // Get + inline bool isNull() const { return this->image_.is_empty(); } + inline int width() const { return this->image_.width(); } + inline int height() const { return this->image_.height(); } + Color getPixelAt(int x, int y) const; + + // Set + void setPixelAt(int x, int y, Color const &color); + + // Color functions + Color color(float u, float v, bool interpolate = true) const; + Color color(Vector2d const &surfacePosition, bool interpolate = true) const; private: - CImg image_; + // Function to compute Gaussian kernel + CImg computeGaussianKernel(int kernelSize, float sigma); + + // Function to perform convolution + CImg convolution(CImg &img, CImg &kernel); + + CImg image_; }; #endif diff --git a/post-processing/bloomshader.cpp b/post-processing/bloomshader.cpp new file mode 100644 index 0000000..5a0ab26 --- /dev/null +++ b/post-processing/bloomshader.cpp @@ -0,0 +1,44 @@ + +#include +#include "bloomshader.h" + +Bloomshader::Bloomshader(Texture image, float threshold, int blurRange) : image(image), threshold(threshold), blurRange(blurRange), + thresholdImage(Texture(image.width() + 2 * blurRange, image.height() + 2 * blurRange)) {} + +void Bloomshader::thresholdshader() { + for(int i = 0; i < image.width(); i++) { + for(int j = 0; j < image.height(); j++){ + if(luminance(image.getPixelAt(i, j)) < threshold){ + thresholdImage.setPixelAt(i + blurRange, j + blurRange, Color(0, 0, 0)); + } else { + thresholdImage.setPixelAt(i + blurRange, j + blurRange, image.getPixelAt(i, j)); + } + } + } + thresholdImage.save("maskResult.png"); + image.save("originalPicture.png"); +} + +Texture Bloomshader::getimage() { + return image; +} + + +void Bloomshader::bloomshader() { + + thresholdImage.gaussianBlur(blurRange * 2, 8.5f); + thresholdImage.scaleBrightness(0.3f); + + thresholdImage.save("blurredMaskResult.png"); + + for(int i = 0; i < image.width(); i++) { + for(int j = 0; j < image.height(); j++){ + Color temp = clamped(image.getPixelAt(i, j) + thresholdImage.getPixelAt(i + blurRange, j + blurRange)); + image.setPixelAt(i, j, temp); + } + } +} + +float Bloomshader::luminance(Color color) { + return dotProduct(Vector3d(color.r, color.g, color.b), Vector3d(0.2126, 0.7152, 0.0722)); +} diff --git a/post-processing/bloomshader.h b/post-processing/bloomshader.h new file mode 100644 index 0000000..403e7a7 --- /dev/null +++ b/post-processing/bloomshader.h @@ -0,0 +1,27 @@ + +#ifndef CG1_TRACER_BLOOMSHADER_H +#define CG1_TRACER_BLOOMSHADER_H + +#include "common/texture.h" +#include "common/vector3d.h" + +class Bloomshader { + +public: + Bloomshader(Texture image, float threshold, int blurRange); + void thresholdshader(); + Texture getimage(); + //void gaussianBlur(int x, int y); + void bloomshader(); + float luminance(Color color); + + +private: + Texture image; + Texture thresholdImage; + float threshold; + int blurRange; +}; + + +#endif //CG1_TRACER_BLOOMSHADER_H diff --git a/renderer/simplerenderer.cpp b/renderer/simplerenderer.cpp index feb2495..6762ee6 100644 --- a/renderer/simplerenderer.cpp +++ b/renderer/simplerenderer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "post-processing/bloomshader.h" void SimpleRenderer::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) { float const aspectRatio = static_cast(height) / width; @@ -73,6 +74,12 @@ Texture SimpleRenderer::renderImage(Scene const &scene, Camera const &camera, in std::cout << "Paths: " << rays << std::endl; std::cout << "Paths per second: " << std::fixed << std::setprecision(0) << rays / seconds << std::endl; + // Post-processing + // Bloom shader + Bloomshader bloomshader = Bloomshader(image, 0.68f, 30); + bloomshader.thresholdshader(); + bloomshader.bloomshader(); + image = bloomshader.getimage(); return image; } From 0d4814c9015fad15531f058b39c310cece3a5a8a Mon Sep 17 00:00:00 2001 From: "m.gaedke" Date: Wed, 25 Jan 2023 10:20:27 +0100 Subject: [PATCH 2/4] Bloom shader finished --- common/texture.cpp | 59 ++------------------ common/texture.h | 16 ++---- post-processing/bloomshader.cpp | 98 ++++++++++++++++++++++++--------- post-processing/bloomshader.h | 22 ++++---- renderer/simplerenderer.cpp | 13 +++-- 5 files changed, 100 insertions(+), 108 deletions(-) diff --git a/common/texture.cpp b/common/texture.cpp index 6f7e845..30a5238 100644 --- a/common/texture.cpp +++ b/common/texture.cpp @@ -3,6 +3,7 @@ #include #include #include +#include Texture::Texture(int width, int height) { this->resize(width, height); } @@ -84,61 +85,11 @@ Color Texture::color(Vector2d const &surfacePosition, bool interpolate) const { return color(surfacePosition.u, surfacePosition.v, interpolate); } -void Texture::gaussianBlur(int kernelSize, float sigma) { - CImg kernel = computeGaussianKernel(kernelSize, sigma); - image_ = convolution(image_, kernel); +CImg Texture::getImage() { + return image_; } -// Function to compute Gaussian kernel -CImg Texture::computeGaussianKernel(int kernelSize, float sigma) { - // Create kernel - CImg kernel(kernelSize, kernelSize, 1, 1); - - // Compute Gaussian kernel - float sum = 0.0f; - int i, j; - for (i = 0; i < kernelSize; i++) { - for (j = 0; j < kernelSize; j++) { - kernel(i, j) = exp(-0.5f * (pow((i - kernelSize / 2.f) / sigma, 2.f) + - pow((j - kernelSize / 2.f) / sigma, 2.f))) / (2 * M_PI * sigma * sigma); - sum += kernel(i, j); - } - } - - // Normalize kernel - kernel /= sum; - - return kernel; +void Texture::setTexture(CImg image){ + image_ = std::move(image); } -// Function to perform convolution -CImg Texture::convolution(CImg &img, CImg &kernel) { - int kernelSize = kernel.width(); - int imgRows = img.height(); - int imgCols = img.width(); - CImg result(imgCols, imgRows, 1, 3); - float sum; - int i, j, m, n; - int kernelRadius = kernelSize / 2; - - // Perform convolution - cimg_forXYC(img, i, j, c) { - sum = 0; - cimg_forY(kernel, m) { - cimg_forX(kernel, n) { - int x = i + n - kernelRadius; - int y = j + m - kernelRadius; - if(x >= 0 && x < imgCols && y >= 0 && y < imgRows){ - sum += img(x, y, 0, c) * kernel(n, m); - } - - } - } - result(i, j, 0, c) = sum; - } - return result; -} - -void Texture::scaleBrightness(float scale) { - image_ *= scale; -} diff --git a/common/texture.h b/common/texture.h index 184a754..4eb21c6 100644 --- a/common/texture.h +++ b/common/texture.h @@ -18,12 +18,6 @@ public: bool load(char const *fileName); bool save(char const *fileName) const; - // Gaussian blur function - void gaussianBlur(int kernelSize, float sigma); - - // Scale function - void scaleBrightness(float scale); - // Get inline bool isNull() const { return this->image_.is_empty(); } inline int width() const { return this->image_.width(); } @@ -32,18 +26,16 @@ public: // Set void setPixelAt(int x, int y, Color const &color); + void setTexture(CImg image); + // Color functions Color color(float u, float v, bool interpolate = true) const; Color color(Vector2d const &surfacePosition, bool interpolate = true) const; + CImg getImage(); + private: - // Function to compute Gaussian kernel - CImg computeGaussianKernel(int kernelSize, float sigma); - - // Function to perform convolution - CImg convolution(CImg &img, CImg &kernel); - CImg image_; }; diff --git a/post-processing/bloomshader.cpp b/post-processing/bloomshader.cpp index 5a0ab26..62cb032 100644 --- a/post-processing/bloomshader.cpp +++ b/post-processing/bloomshader.cpp @@ -2,43 +2,87 @@ #include #include "bloomshader.h" -Bloomshader::Bloomshader(Texture image, float threshold, int blurRange) : image(image), threshold(threshold), blurRange(blurRange), - thresholdImage(Texture(image.width() + 2 * blurRange, image.height() + 2 * blurRange)) {} +Bloomshader::Bloomshader(CImg image) : image(image) {} -void Bloomshader::thresholdshader() { - for(int i = 0; i < image.width(); i++) { - for(int j = 0; j < image.height(); j++){ - if(luminance(image.getPixelAt(i, j)) < threshold){ - thresholdImage.setPixelAt(i + blurRange, j + blurRange, Color(0, 0, 0)); - } else { - thresholdImage.setPixelAt(i + blurRange, j + blurRange, image.getPixelAt(i, j)); - } - } + +CImg Bloomshader::bloom(float threshold, int kernelSize, float sigma, float intensity) { + // Apply threshold to image + //CImg brightPixels = image_.get_threshold(threshold); + //brightPixels.save("brightpixels.png"); + + // Apply gaussian blur to bright pixels + CImg kernel = computeGaussianKernel(kernelSize, sigma); + CImg blurred = convolution(image, kernel); + for(int i = 0; i < 3; i++){ + kernel = computeGaussianKernel(kernelSize, sigma); + blurred = convolution(image, kernel); + blurred *= intensity; + } + + // Add blurred image back to original image + cimg_forXYC(image, x, y, c) { + float value = image(x,y,0,c) + blurred(x,y,0,c); + image(x,y,0,c) = (value > 1.0f) ? 1.0f : value; } - thresholdImage.save("maskResult.png"); - image.save("originalPicture.png"); -} -Texture Bloomshader::getimage() { return image; } +void Bloomshader::gaussianBlur(int kernelSize, float sigma) { + CImg kernel = computeGaussianKernel(kernelSize, sigma); + image = convolution(image, kernel); +} -void Bloomshader::bloomshader() { +// Function to compute Gaussian kernel +CImg Bloomshader::computeGaussianKernel(int kernelSize, float sigma) { + // Create kernel + CImg kernel(kernelSize, kernelSize, 1, 1); - thresholdImage.gaussianBlur(blurRange * 2, 8.5f); - thresholdImage.scaleBrightness(0.3f); - - thresholdImage.save("blurredMaskResult.png"); - - for(int i = 0; i < image.width(); i++) { - for(int j = 0; j < image.height(); j++){ - Color temp = clamped(image.getPixelAt(i, j) + thresholdImage.getPixelAt(i + blurRange, j + blurRange)); - image.setPixelAt(i, j, temp); + // Compute Gaussian kernel + float sum = 0.0f; + int i, j; + for (i = 0; i < kernelSize; i++) { + for (j = 0; j < kernelSize; j++) { + kernel(i, j) = exp(-0.5f * (pow((i - kernelSize / 2.f) / sigma, 2.f) + + pow((j - kernelSize / 2.f) / sigma, 2.f))) / (2 * M_PI * sigma * sigma); + sum += kernel(i, j); } } + + // Normalize kernel + kernel /= sum; + + return kernel; } -float Bloomshader::luminance(Color color) { - return dotProduct(Vector3d(color.r, color.g, color.b), Vector3d(0.2126, 0.7152, 0.0722)); +// Function to perform convolution +CImg Bloomshader::convolution(CImg &img, CImg &kernel) { + int kernelSize = kernel.width(); + int imgRows = img.height(); + int imgCols = img.width(); + CImg result(imgCols, imgRows, 1, 3); + float sum; + int i, j, m, n; + int kernelRadius = kernelSize / 2; + + // Perform convolution + cimg_forXYC(img, i, j, c) { + sum = 0; + cimg_forY(kernel, m) { + cimg_forX(kernel, n) { + int x = i + n - kernelRadius; + int y = j + m - kernelRadius; + if(x >= 0 && x < imgCols && y >= 0 && y < imgRows){ + sum += img(x, y, 0, c) * kernel(n, m); + } + + } + } + result(i, j, 0, c) = sum; + } + return result; +} + +void Bloomshader::scaleBrightness(float scale) { + image *= scale; } diff --git a/post-processing/bloomshader.h b/post-processing/bloomshader.h index 403e7a7..addcf0a 100644 --- a/post-processing/bloomshader.h +++ b/post-processing/bloomshader.h @@ -8,19 +8,19 @@ class Bloomshader { public: - Bloomshader(Texture image, float threshold, int blurRange); - void thresholdshader(); - Texture getimage(); - //void gaussianBlur(int x, int y); - void bloomshader(); - float luminance(Color color); - + Bloomshader(CImg image); + CImg bloom(float threshold, int kernelSize, float sigma, float intensity); private: - Texture image; - Texture thresholdImage; - float threshold; - int blurRange; + void scaleBrightness(float scale); + void gaussianBlur(int kernelSize, float sigma); + + CImg convolution(CImg &img, CImg &kernel); + CImg computeGaussianKernel(int kernelSize, float sigma); + + + + CImg image; }; diff --git a/renderer/simplerenderer.cpp b/renderer/simplerenderer.cpp index 6762ee6..ffd69e2 100644 --- a/renderer/simplerenderer.cpp +++ b/renderer/simplerenderer.cpp @@ -76,10 +76,15 @@ Texture SimpleRenderer::renderImage(Scene const &scene, Camera const &camera, in // Post-processing // Bloom shader - Bloomshader bloomshader = Bloomshader(image, 0.68f, 30); - bloomshader.thresholdshader(); - bloomshader.bloomshader(); - image = bloomshader.getimage(); + //Bloomshader bloomshader = Bloomshader(image, 0.48f, 10); + //bloomshader.thresholdshader(); + + image.save("original.png"); + + Bloomshader bloomEffect = Bloomshader(image.getImage()); + image.setTexture(bloomEffect.bloom(0.55f, 5, 10.0f, 0.06f)); + + //image = bloomshader.getimage(); return image; } From f24011f642ee662277b5fcbbab1227f51613fdd0 Mon Sep 17 00:00:00 2001 From: "m.gaedke" Date: Wed, 25 Jan 2023 21:03:21 +0100 Subject: [PATCH 3/4] DepthofField Function added in this branch still runs into segFault --- CMakeLists.txt | 6 ++- camera/perspectivecamera.h | 6 +++ ex4.cpp | 84 +++++++++++++++++++++-------------- renderer/simplerenderer.cpp | 4 -- shader/depthoffieldshader.cpp | 47 ++++++++++++++++++++ shader/depthoffieldshader.h | 33 ++++++++++++++ 6 files changed, 141 insertions(+), 39 deletions(-) create mode 100644 shader/depthoffieldshader.cpp create mode 100644 shader/depthoffieldshader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ed9dac..52d5575 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ file(GLOB shader_src "shader/*.cpp") # The tracey library add_library(tracey STATIC ${common_src} ${noise_src} ${camera_src} ${light_src} ${primitive_src} ${renderer_src} ${scene_src} ${shader_src} light/ambientlight.cpp light/ambientlight.h - light/spotlight.cpp light/spotlight.h post-processing/bloomshader.cpp post-processing/bloomshader.h) + light/spotlight.cpp light/spotlight.h post-processing/bloomshader.cpp post-processing/bloomshader.h shader/depthoffieldshader.cpp shader/depthoffieldshader.h) if(NOT WIN32) target_link_libraries(tracey ${CMAKE_THREAD_LIBS_INIT} ${X11_LIBRARIES}) endif() @@ -73,6 +73,10 @@ endif() add_executable(fancy1 fancy1.cpp) target_link_libraries(fancy1 tracey) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") + +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") + diff --git a/camera/perspectivecamera.h b/camera/perspectivecamera.h index 638f392..0d0f8f2 100644 --- a/camera/perspectivecamera.h +++ b/camera/perspectivecamera.h @@ -36,6 +36,12 @@ public: // Camera functions Ray createRay(float x, float y) const override; + //Getter + Vector3d getPosition() const { return position; } + Vector3d getRightDirection() const { return rightDirection; } + Vector3d getUpDirection() const { return upDirection; } + + protected: Vector3d position; Vector3d forwardDirection; diff --git a/ex4.cpp b/ex4.cpp index cadf20c..678962c 100644 --- a/ex4.cpp +++ b/ex4.cpp @@ -16,6 +16,7 @@ #include "shader/mirrorshader.h" #include "shader/phongshader.h" #include "shader/cooktorranceshader.h" +#include "shader/depthoffieldshader.h" #include "light/ambientlight.h" #include "light/pointlight.h" @@ -25,40 +26,6 @@ int main() { // Let's create a simple scene... SimpleScene scene; - // Add shaders - auto mirror = std::make_shared(); - auto white = std::make_shared(Color(0.9f, 0.9f, 0.9f)); - auto red = std::make_shared(Color(1.0f, 0.3f, 0.2f)); - auto blue = std::make_shared(Color(0.2f, 0.3f, 1.0f)); - auto orange = std::make_shared(Color(1.0f, 0.64f, 0.0f), 1.0f, Color(1.0f, 1.0f, 1.0f), 1.0f, 25.0f); - auto gold= std::make_shared(Color(0.83f, 0.69f, 0.22f), Color(1.0f, 1.0f, 0.0f), 1.2f, 0.2f); - auto blueMetallic = std::make_shared("data/blue-metallic-paint.binary", Color(7.0f, 7.0f, 7.0f)); - auto darkRed = std::make_shared("data/dark-red-paint.binary", Color(7.0f, 7.0f, 7.0f)); - - // Set up the walls - // --------------------------------------------------------------------------- - scene.add(std::make_shared(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), mirror)); - - scene.add(std::make_shared(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), mirror)); - scene.add(std::make_shared(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white)); - scene.add(std::make_shared(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white)); - scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue)); - scene.add(std::make_shared(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red)); - - scene.add(std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, blueMetallic)); - scene.add(std::make_shared(Vector3d(0.0f, 2.0f, 0.0f), 1.0f, orange)); - scene.add(std::make_shared(Vector3d(3.0f, 0.0f, 0.0f), 1.0f, darkRed)); - - // Add the teapot - auto teapot = std::make_shared(gold); - teapot->loadObj("data/teapot.obj", Vector3d(3.0f, 3.0f, 3.0f), Vector3d(0.0f, -5.0f, 0.0f)); - scene.add(teapot); - - // Add ambient light - scene.add(std::make_shared(0.15f)); - scene.add(std::make_shared(Vector3d(0.0f, 4.0f, -4.0f), 15.0f)); - scene.add(std::make_shared(Vector3d(0.0f, 4.0f, 4.0f), 15.0f)); - // Set up the camera PerspectiveCamera camera; camera.setFovAngle(90.0f); @@ -66,6 +33,55 @@ int main() { camera.setForwardDirection(Vector3d(0.0f, 0.0f, 1.0f)); camera.setUpDirection(Vector3d(0.0f, 1.0f, 0.0f)); + // Add shaders + auto mirror = std::make_shared(); + auto white = std::make_shared(Color(0.9f, 0.9f, 0.9f)); + auto red = std::make_shared(Color(1.0f, 0.3f, 0.2f)); + auto blue = std::make_shared(Color(0.2f, 0.3f, 1.0f)); + auto orange = std::make_shared(Color(1.0f, 0.64f, 0.0f), 1.0f, Color(1.0f, 1.0f, 1.0f), 1.0f, 25.0f); + auto gold= std::make_shared(Color(0.83f, 0.69f, 0.22f), Color(1.0f, 1.0f, 0.0f), 1.2f, 0.2f); + auto blueMetallic = std::make_shared("../data/blue-metallic-paint.binary", Color(7.0f, 7.0f, 7.0f)); + auto darkRed = std::make_shared("../data/dark-red-paint.binary", Color(7.0f, 7.0f, 7.0f)); + + auto dofShader = std::make_shared(scene, Color(0.9f, 0.9f, 0.9f), 100, 0.1f, 10.0f, 50.0f, camera); + + + + // Set up the walls + // --------------------------------------------------------------------------- + + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), mirror)); + + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), mirror)); + scene.add(std::make_shared(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white)); + scene.add(std::make_shared(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white)); + scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), dofShader)); + scene.add(std::make_shared(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red)); + + scene.add(std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, blueMetallic)); + scene.add(std::make_shared(Vector3d(0.0f, 2.0f, 0.0f), 1.0f, orange)); + scene.add(std::make_shared(Vector3d(3.0f, 0.0f, 0.0f), 1.0f, darkRed)); + + // Create a DOFShader instance with the desired aperture size, focal distance, and focal length + + // Use the DOFShader instance as the shader for an object in the scene + auto sphere = std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, dofShader); + + // Add the sphere to the scene + scene.add(sphere); + + // Add the teapot + auto teapot = std::make_shared(gold); + teapot->loadObj("../data/teapot.obj", Vector3d(3.0f, 3.0f, 3.0f), Vector3d(0.0f, -5.0f, 0.0f)); + scene.add(teapot); + + // Add ambient light + scene.add(std::make_shared(0.15f)); + //scene.add(std::make_shared(Vector3d(0.0f, 4.0f, -4.0f), 15.0f)); + scene.add(std::make_shared(Vector3d(0.0f, 2.5f, -4.0f), 7.0f)); + + + // Render the scene SimpleRenderer renderer; renderer.renderImage(scene, camera, 512, 512).save("result.png"); diff --git a/renderer/simplerenderer.cpp b/renderer/simplerenderer.cpp index ffd69e2..fea71a3 100644 --- a/renderer/simplerenderer.cpp +++ b/renderer/simplerenderer.cpp @@ -76,15 +76,11 @@ Texture SimpleRenderer::renderImage(Scene const &scene, Camera const &camera, in // Post-processing // Bloom shader - //Bloomshader bloomshader = Bloomshader(image, 0.48f, 10); - //bloomshader.thresholdshader(); image.save("original.png"); Bloomshader bloomEffect = Bloomshader(image.getImage()); image.setTexture(bloomEffect.bloom(0.55f, 5, 10.0f, 0.06f)); - //image = bloomshader.getimage(); - return image; } diff --git a/shader/depthoffieldshader.cpp b/shader/depthoffieldshader.cpp new file mode 100644 index 0000000..ab6672e --- /dev/null +++ b/shader/depthoffieldshader.cpp @@ -0,0 +1,47 @@ +#include + +#include "depthoffieldshader.h" + + +DOFShader::DOFShader(SimpleScene& _scene, Color const &_diffuseColor, int _numSamples, float _aperture, float _focalDistance, float _focalLength, PerspectiveCamera& _camera) : scene(_scene), diffuseColor(_diffuseColor), numSamples(_numSamples), aperture(_aperture), +focalDistance(_focalDistance), focalLength(_focalLength), camera(_camera) {} + +std::random_device DOFShader::rd; +std::mt19937 DOFShader::gen(DOFShader::rd()); + +Color DOFShader::shade(Scene const &scene, Ray const &ray) const { + Color color; + + // Accumulate the light over all light sources + for (const auto &light : scene.lights()) { + Light::Illumination const illum = light->illuminate(scene, ray); + Color const diffuse = this->diffuseColor * std::max(dotProduct(-illum.direction, ray.normal), 0.0f); + // Add the sample color to the final color + color += diffuse * sample(ray, illum); + } + + return color; +} + +Color DOFShader::sample(Ray ray, Light::Illumination const &illum) const { + + std::uniform_real_distribution dis(-1.0, 1.0); + + // calculate the point of focus + Vector3d focusPoint = ray.origin + ray.direction * focalDistance; + + // create a random point on the aperture + Vector3d rnd = Vector3d(dis(gen), dis(gen), 0); + Vector3d offset = aperture * (rnd.x * camera.getRightDirection() + rnd.y * camera.getUpDirection()); + + // create the new ray with the offset point + Vector3d dofRayStart = camera.getPosition() + offset; + Vector3d dofRayDir = normalized(focusPoint - (camera.getPosition() + offset)); + + Ray dofRay = Ray(dofRayStart, dofRayDir); + + // trace the new ray and sample the color + + Color tracedColor = scene.traceRay(dofRay); + return tracedColor; +} diff --git a/shader/depthoffieldshader.h b/shader/depthoffieldshader.h new file mode 100644 index 0000000..d9adeb9 --- /dev/null +++ b/shader/depthoffieldshader.h @@ -0,0 +1,33 @@ +#ifndef DEPTHOFFIELDSHADER_H +#define DEPTHOFFIELDSHADER_H + +#include "shader/shader.h" +#include "light/light.h" +#include "camera/perspectivecamera.h" +#include +#include "scene/simplescene.h" + +class DOFShader : public Shader { + +public: + // Constructor / Desctructor + DOFShader(SimpleScene& _scene, Color const &_diffuseColor, int _numSamples, float _aperture, float _focalDistance, float _focalLength, PerspectiveCamera& _camera); + virtual ~DOFShader() = default; + + // Shader functions + virtual Color shade(Scene const &scene, Ray const &ray) const; + +private: + float aperture, focalDistance, focalLength; + int numSamples; + PerspectiveCamera& camera; + SimpleScene& scene; + Color diffuseColor; + static std::random_device rd; + static std::mt19937 gen; + + + Color sample(Ray ray, Light::Illumination const &illum) const; +}; + +#endif \ No newline at end of file From f5347bb07a80bd4290081ff553ad3f57ca0776df Mon Sep 17 00:00:00 2001 From: "m.gaedke" Date: Thu, 26 Jan 2023 22:56:23 +0100 Subject: [PATCH 4/4] Field of View renderer finally working pretty good + some restructioring of code --- CMakeLists.txt | 6 +- camera/camera.h | 6 + camera/perspectivecamera.h | 11 +- ex4.cpp | 32 +++-- .../bloom.cpp | 14 +- .../bloomshader.h => post_processing/bloom.h | 10 +- renderer/depthoffieldrenderer.cpp | 124 ++++++++++++++++++ renderer/depthoffieldrenderer.h | 35 +++++ renderer/simplerenderer.cpp | 6 +- renderer/simplerenderer.h | 7 +- shader/depthoffieldshader.cpp | 47 ------- shader/depthoffieldshader.h | 33 ----- 12 files changed, 209 insertions(+), 122 deletions(-) rename post-processing/bloomshader.cpp => post_processing/bloom.cpp (82%) rename post-processing/bloomshader.h => post_processing/bloom.h (73%) create mode 100644 renderer/depthoffieldrenderer.cpp create mode 100644 renderer/depthoffieldrenderer.h delete mode 100644 shader/depthoffieldshader.cpp delete mode 100644 shader/depthoffieldshader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 52d5575..466550e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,11 +24,13 @@ file(GLOB primitive_src "primitive/*.cpp") file(GLOB renderer_src "renderer/*.cpp") file(GLOB scene_src "scene/*.cpp") file(GLOB shader_src "shader/*.cpp") +file(GLOB effect_src "effect/*.cpp") +file(GLOB post_processing_src "post_processing/*.cpp") # The tracey library add_library(tracey STATIC ${common_src} ${noise_src} ${camera_src} ${light_src} - ${primitive_src} ${renderer_src} ${scene_src} ${shader_src} light/ambientlight.cpp light/ambientlight.h - light/spotlight.cpp light/spotlight.h post-processing/bloomshader.cpp post-processing/bloomshader.h shader/depthoffieldshader.cpp shader/depthoffieldshader.h) + ${primitive_src} ${renderer_src} ${scene_src} ${shader_src} ${effect_src} + ${post_processing_src}) if(NOT WIN32) target_link_libraries(tracey ${CMAKE_THREAD_LIBS_INIT} ${X11_LIBRARIES}) endif() diff --git a/camera/camera.h b/camera/camera.h index 93d82bf..2933d46 100644 --- a/camera/camera.h +++ b/camera/camera.h @@ -12,6 +12,12 @@ public: // Camera functions virtual Ray createRay(float x, float y) const = 0; + + // Setter methods + virtual Vector3d getPosition() const = 0; + virtual Vector3d getRightDirection() const = 0; + virtual Vector3d getUpDirection() const = 0; }; + #endif diff --git a/camera/perspectivecamera.h b/camera/perspectivecamera.h index 0d0f8f2..d935200 100644 --- a/camera/perspectivecamera.h +++ b/camera/perspectivecamera.h @@ -13,11 +13,6 @@ public: // Set void setPosition(Vector3d const &position) { this->position = position; } void setForwardDirection(Vector3d const &forwardDirection) { - // IMPLEMENT ME - // Set up a left-handed coordinate system, - // in which the camera looks along the positive z-Axis - // Set up a left-handed coordinate system, - // in which the camera looks along the positive z-Axis std::tie(this->forwardDirection, this->upDirection, this->rightDirection) = orthoNormalized(forwardDirection, this->upDirection, crossProduct(this->upDirection, forwardDirection)); } void setUpDirection(Vector3d const &upDirection) { @@ -37,9 +32,9 @@ public: Ray createRay(float x, float y) const override; //Getter - Vector3d getPosition() const { return position; } - Vector3d getRightDirection() const { return rightDirection; } - Vector3d getUpDirection() const { return upDirection; } + Vector3d getPosition() const override { return position; } + Vector3d getRightDirection() const override{ return rightDirection; } + Vector3d getUpDirection() const override { return upDirection; } protected: diff --git a/ex4.cpp b/ex4.cpp index 678962c..ee1154a 100644 --- a/ex4.cpp +++ b/ex4.cpp @@ -16,7 +16,7 @@ #include "shader/mirrorshader.h" #include "shader/phongshader.h" #include "shader/cooktorranceshader.h" -#include "shader/depthoffieldshader.h" +#include "renderer/depthoffieldrenderer.h" #include "light/ambientlight.h" #include "light/pointlight.h" @@ -43,8 +43,8 @@ int main() { auto blueMetallic = std::make_shared("../data/blue-metallic-paint.binary", Color(7.0f, 7.0f, 7.0f)); auto darkRed = std::make_shared("../data/dark-red-paint.binary", Color(7.0f, 7.0f, 7.0f)); - auto dofShader = std::make_shared(scene, Color(0.9f, 0.9f, 0.9f), 100, 0.1f, 10.0f, 50.0f, camera); - + // DOF Shader + bool dofShader = true; // Set up the walls @@ -55,20 +55,13 @@ int main() { scene.add(std::make_shared(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), mirror)); scene.add(std::make_shared(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white)); scene.add(std::make_shared(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white)); - scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), dofShader)); + scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue)); scene.add(std::make_shared(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red)); scene.add(std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, blueMetallic)); scene.add(std::make_shared(Vector3d(0.0f, 2.0f, 0.0f), 1.0f, orange)); scene.add(std::make_shared(Vector3d(3.0f, 0.0f, 0.0f), 1.0f, darkRed)); - - // Create a DOFShader instance with the desired aperture size, focal distance, and focal length - - // Use the DOFShader instance as the shader for an object in the scene - auto sphere = std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, dofShader); - - // Add the sphere to the scene - scene.add(sphere); + scene.add(std::make_shared(Vector3d(-3.0f, -3.3f, -4.0f), 1.0f, mirror)); // Add the teapot auto teapot = std::make_shared(gold); @@ -83,8 +76,19 @@ int main() { // Render the scene - SimpleRenderer renderer; - renderer.renderImage(scene, camera, 512, 512).save("result.png"); + // SimpleRenderer renderer; + // renderer.renderImage(scene, camera, 1024, 1024).save("result.png"); + + + // initialize renderer: aperture = lens thickness, secondaryRayCount = how many rays per pixel are created + // focalLength = the area which is in focus + DOFRenderer renderer(0.2, 100, 10.0f); + + // Use DOFRenderer to raytrace + Texture image = renderer.renderImage(scene, camera, 1024, 1024); + + // save image + image.save("result.png"); return 0; } diff --git a/post-processing/bloomshader.cpp b/post_processing/bloom.cpp similarity index 82% rename from post-processing/bloomshader.cpp rename to post_processing/bloom.cpp index 62cb032..93291fe 100644 --- a/post-processing/bloomshader.cpp +++ b/post_processing/bloom.cpp @@ -1,11 +1,11 @@ #include -#include "bloomshader.h" +#include "bloom.h" -Bloomshader::Bloomshader(CImg image) : image(image) {} +Bloom::Bloom(CImg image) : image(image) {} -CImg Bloomshader::bloom(float threshold, int kernelSize, float sigma, float intensity) { +CImg Bloom::bloom(float threshold, int kernelSize, float sigma, float intensity) { // Apply threshold to image //CImg brightPixels = image_.get_threshold(threshold); //brightPixels.save("brightpixels.png"); @@ -28,13 +28,13 @@ CImg Bloomshader::bloom(float threshold, int kernelSize, float sigma, flo return image; } -void Bloomshader::gaussianBlur(int kernelSize, float sigma) { +void Bloom::gaussianBlur(int kernelSize, float sigma) { CImg kernel = computeGaussianKernel(kernelSize, sigma); image = convolution(image, kernel); } // Function to compute Gaussian kernel -CImg Bloomshader::computeGaussianKernel(int kernelSize, float sigma) { +CImg Bloom::computeGaussianKernel(int kernelSize, float sigma) { // Create kernel CImg kernel(kernelSize, kernelSize, 1, 1); @@ -56,7 +56,7 @@ CImg Bloomshader::computeGaussianKernel(int kernelSize, float sigma) { } // Function to perform convolution -CImg Bloomshader::convolution(CImg &img, CImg &kernel) { +CImg Bloom::convolution(CImg &img, CImg &kernel) { int kernelSize = kernel.width(); int imgRows = img.height(); int imgCols = img.width(); @@ -83,6 +83,6 @@ CImg Bloomshader::convolution(CImg &img, CImg &kernel) { return result; } -void Bloomshader::scaleBrightness(float scale) { +void Bloom::scaleBrightness(float scale) { image *= scale; } diff --git a/post-processing/bloomshader.h b/post_processing/bloom.h similarity index 73% rename from post-processing/bloomshader.h rename to post_processing/bloom.h index addcf0a..694b0d8 100644 --- a/post-processing/bloomshader.h +++ b/post_processing/bloom.h @@ -1,14 +1,14 @@ -#ifndef CG1_TRACER_BLOOMSHADER_H -#define CG1_TRACER_BLOOMSHADER_H +#ifndef CG1_TRACER_BLOOM_H +#define CG1_TRACER_BLOOM_H #include "common/texture.h" #include "common/vector3d.h" -class Bloomshader { +class Bloom { public: - Bloomshader(CImg image); + Bloom(CImg image); CImg bloom(float threshold, int kernelSize, float sigma, float intensity); private: @@ -24,4 +24,4 @@ private: }; -#endif //CG1_TRACER_BLOOMSHADER_H +#endif //CG1_TRACER_BLOOM_H diff --git a/renderer/depthoffieldrenderer.cpp b/renderer/depthoffieldrenderer.cpp new file mode 100644 index 0000000..aba7d57 --- /dev/null +++ b/renderer/depthoffieldrenderer.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include "depthoffieldrenderer.h" +#include +#include "post_processing/bloom.h" + + +DOFRenderer::DOFRenderer(float _aperture, int _secondaryRayCount, float _focalLength) : aperture(_aperture), + numSamples(_secondaryRayCount), focalLength(_focalLength) {} + +std::random_device DOFRenderer::rd; +std::mt19937 DOFRenderer::gen(DOFRenderer::rd()); + +Color DOFRenderer::sample(const Ray &ray, const Scene& scene, const Camera& camera) const { + + std::uniform_real_distribution dis(-1.0, 1.0); + + // calculate the point of focus + Vector3d focusPoint = ray.origin + ray.direction * focalLength; + + // Final color + Color finalColor; + + // Calculate all secondary Rays + for (int i = 0; i < numSamples; i++) { + // create a random point on the aperture + Vector3d rnd = Vector3d(dis(gen), dis(gen), 0); + Vector3d apertureOffset = aperture * (rnd.x * camera.getRightDirection() + rnd.y * camera.getUpDirection()); + + // create the new ray with the offset point + Vector3d dofRayOrigin = ray.origin + apertureOffset; + Vector3d dofRayDirection = normalized(focusPoint - dofRayOrigin); + Ray dofRay(dofRayOrigin, dofRayDirection); + + // get Color of the new Ray + finalColor += scene.traceRay(dofRay); + } + + + // trace the new ray and return the color + return finalColor /= float(numSamples);; +} + +void DOFRenderer::renderThread(const Scene *scene, Camera const *camera, Texture *image, const DOFRenderer *renderer, int width, int widthStep, int widthOffset, int height, int heightStep, int heightOffset, std::atomic *k, int const stepSize) { + float const aspectRatio = static_cast(height) / width; + for (int y = heightOffset; y < height; y += heightStep) { + for (int x = widthOffset; x < width; x += widthStep) { + Ray ray = camera->createRay((static_cast(x) / width * 2 - 1), -(static_cast(y) / height * 2 - 1) * aspectRatio); + + // Trace rays with DOF + image->setPixelAt(x, y, clamped(renderer->sample(ray, *scene, *camera))); + + // Super hacky progress bar! + if (++*k % stepSize == 0) { + std::cout << "=" << std::flush; + } + } + } +} + + +Texture DOFRenderer::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 << "(SimpleRenderer): 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, this, width, nThreads, t, height, 1, 0, &k, stepSize); + } + + // Call the renderThread function yourself + renderThread(&scene, &camera, &image, this, width, nThreads, nThreads - 1, height, 1, 0, &k, stepSize); + + // 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; + + // Post-processing + // Bloom shader + + image.save("original.png"); + + Bloom bloomEffect = Bloom(image.getImage()); + image.setTexture(bloomEffect.bloom(0.55f, 5, 10.0f, 0.06f)); + + return image; +} \ No newline at end of file diff --git a/renderer/depthoffieldrenderer.h b/renderer/depthoffieldrenderer.h new file mode 100644 index 0000000..d195735 --- /dev/null +++ b/renderer/depthoffieldrenderer.h @@ -0,0 +1,35 @@ +#ifndef DEPTHOFFIELDSHADER_H +#define DEPTHOFFIELDSHADER_H + +#include "camera/camera.h" +#include +#include "renderer/renderer.h" +#include "scene/simplescene.h" + + +class DOFRenderer : public Renderer { + static void renderThread(const Scene *scene, const Camera *camera, Texture *image, const DOFRenderer *renderer, int width, int widthStep, + int widthOffset, int height, int heightStep, int heightOffset, std::atomic *k, + const int stepSize); + +public: + // Constructor + DOFRenderer(float _aperture, int _secondaryRayCount, float _focalLength); + ~DOFRenderer() override = default; + + //Render Functions + Texture renderImage(Scene const &scene, Camera const &camera, int width, int height) override; + + // DOF sampler + Color sample(const Ray &ray, const Scene& scene, const Camera& camera) const; + +private: + float aperture, focalLength; + int numSamples; + + static std::random_device rd; + static std::mt19937 gen; + +}; + +#endif \ No newline at end of file diff --git a/renderer/simplerenderer.cpp b/renderer/simplerenderer.cpp index fea71a3..3647efc 100644 --- a/renderer/simplerenderer.cpp +++ b/renderer/simplerenderer.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "post-processing/bloomshader.h" +#include "post_processing/bloom.h" void SimpleRenderer::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) { float const aspectRatio = static_cast(height) / width; @@ -79,8 +79,8 @@ Texture SimpleRenderer::renderImage(Scene const &scene, Camera const &camera, in image.save("original.png"); - Bloomshader bloomEffect = Bloomshader(image.getImage()); + Bloom bloomEffect = Bloom(image.getImage()); image.setTexture(bloomEffect.bloom(0.55f, 5, 10.0f, 0.06f)); return image; -} +} \ No newline at end of file diff --git a/renderer/simplerenderer.h b/renderer/simplerenderer.h index 21e1f69..c1c9ed2 100644 --- a/renderer/simplerenderer.h +++ b/renderer/simplerenderer.h @@ -3,11 +3,12 @@ #include #include "renderer/renderer.h" +#include class SimpleRenderer : public Renderer { - 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); + static void renderThread(const Scene *scene, const Camera *camera, Texture *image, int width, int widthStep, + int widthOffset, int height, int heightStep, int heightOffset, std::atomic *k, + const int stepSize); public: // Constructor / Destructor diff --git a/shader/depthoffieldshader.cpp b/shader/depthoffieldshader.cpp deleted file mode 100644 index ab6672e..0000000 --- a/shader/depthoffieldshader.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include - -#include "depthoffieldshader.h" - - -DOFShader::DOFShader(SimpleScene& _scene, Color const &_diffuseColor, int _numSamples, float _aperture, float _focalDistance, float _focalLength, PerspectiveCamera& _camera) : scene(_scene), diffuseColor(_diffuseColor), numSamples(_numSamples), aperture(_aperture), -focalDistance(_focalDistance), focalLength(_focalLength), camera(_camera) {} - -std::random_device DOFShader::rd; -std::mt19937 DOFShader::gen(DOFShader::rd()); - -Color DOFShader::shade(Scene const &scene, Ray const &ray) const { - Color color; - - // Accumulate the light over all light sources - for (const auto &light : scene.lights()) { - Light::Illumination const illum = light->illuminate(scene, ray); - Color const diffuse = this->diffuseColor * std::max(dotProduct(-illum.direction, ray.normal), 0.0f); - // Add the sample color to the final color - color += diffuse * sample(ray, illum); - } - - return color; -} - -Color DOFShader::sample(Ray ray, Light::Illumination const &illum) const { - - std::uniform_real_distribution dis(-1.0, 1.0); - - // calculate the point of focus - Vector3d focusPoint = ray.origin + ray.direction * focalDistance; - - // create a random point on the aperture - Vector3d rnd = Vector3d(dis(gen), dis(gen), 0); - Vector3d offset = aperture * (rnd.x * camera.getRightDirection() + rnd.y * camera.getUpDirection()); - - // create the new ray with the offset point - Vector3d dofRayStart = camera.getPosition() + offset; - Vector3d dofRayDir = normalized(focusPoint - (camera.getPosition() + offset)); - - Ray dofRay = Ray(dofRayStart, dofRayDir); - - // trace the new ray and sample the color - - Color tracedColor = scene.traceRay(dofRay); - return tracedColor; -} diff --git a/shader/depthoffieldshader.h b/shader/depthoffieldshader.h deleted file mode 100644 index d9adeb9..0000000 --- a/shader/depthoffieldshader.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DEPTHOFFIELDSHADER_H -#define DEPTHOFFIELDSHADER_H - -#include "shader/shader.h" -#include "light/light.h" -#include "camera/perspectivecamera.h" -#include -#include "scene/simplescene.h" - -class DOFShader : public Shader { - -public: - // Constructor / Desctructor - DOFShader(SimpleScene& _scene, Color const &_diffuseColor, int _numSamples, float _aperture, float _focalDistance, float _focalLength, PerspectiveCamera& _camera); - virtual ~DOFShader() = default; - - // Shader functions - virtual Color shade(Scene const &scene, Ray const &ray) const; - -private: - float aperture, focalDistance, focalLength; - int numSamples; - PerspectiveCamera& camera; - SimpleScene& scene; - Color diffuseColor; - static std::random_device rd; - static std::mt19937 gen; - - - Color sample(Ray ray, Light::Illumination const &illum) const; -}; - -#endif \ No newline at end of file