Merge branch 'Bloomshader'
Adding DOFRenderer and postProcessing bloom effect to master
This commit is contained in:
commit
ce1fe4dd9a
12 changed files with 372 additions and 41 deletions
|
@ -24,10 +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)
|
||||
${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()
|
||||
|
@ -72,6 +75,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")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
@ -36,6 +31,12 @@ public:
|
|||
// Camera functions
|
||||
Ray createRay(float x, float y) const override;
|
||||
|
||||
//Getter
|
||||
Vector3d getPosition() const override { return position; }
|
||||
Vector3d getRightDirection() const override{ return rightDirection; }
|
||||
Vector3d getUpDirection() const override { return upDirection; }
|
||||
|
||||
|
||||
protected:
|
||||
Vector3d position;
|
||||
Vector3d forwardDirection;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
Texture::Texture(int width, int height) { this->resize(width, height); }
|
||||
|
||||
|
@ -83,3 +84,12 @@ 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);
|
||||
}
|
||||
|
||||
CImg<float> Texture::getImage() {
|
||||
return image_;
|
||||
}
|
||||
|
||||
void Texture::setTexture(CImg<float> image){
|
||||
image_ = std::move(image);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,30 +9,34 @@ 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;
|
||||
// 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);
|
||||
// Set
|
||||
void setPixelAt(int x, int y, Color const &color);
|
||||
void setTexture(CImg<float> image);
|
||||
|
||||
// Color functions
|
||||
Color color(float u, float v, bool interpolate = true) const;
|
||||
Color color(Vector2d const &surfacePosition, bool interpolate = true) const;
|
||||
|
||||
// Color functions
|
||||
Color color(float u, float v, bool interpolate = true) const;
|
||||
Color color(Vector2d const &surfacePosition, bool interpolate = true) const;
|
||||
|
||||
CImg<float> getImage();
|
||||
|
||||
private:
|
||||
CImg<float> image_;
|
||||
CImg<float> image_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
46
ex4.cpp
46
ex4.cpp
|
@ -16,6 +16,7 @@
|
|||
#include "shader/mirrorshader.h"
|
||||
#include "shader/phongshader.h"
|
||||
#include "shader/cooktorranceshader.h"
|
||||
#include "renderer/depthoffieldrenderer.h"
|
||||
|
||||
#include "light/ambientlight.h"
|
||||
#include "light/pointlight.h"
|
||||
|
@ -25,6 +26,13 @@ int main() {
|
|||
// Let's create a simple scene...
|
||||
SimpleScene scene;
|
||||
|
||||
// Set up the camera
|
||||
PerspectiveCamera camera;
|
||||
camera.setFovAngle(90.0f);
|
||||
camera.setPosition(Vector3d(0.0f, 0.0f, -10.0f));
|
||||
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<MirrorShader>();
|
||||
auto white = std::make_shared<LambertShader>(Color(0.9f, 0.9f, 0.9f));
|
||||
|
@ -32,11 +40,16 @@ int main() {
|
|||
auto blue = std::make_shared<LambertShader>(Color(0.2f, 0.3f, 1.0f));
|
||||
auto orange = std::make_shared<PhongShader>(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<CookTorranceShader>(Color(0.83f, 0.69f, 0.22f), Color(1.0f, 1.0f, 0.0f), 1.2f, 0.2f);
|
||||
auto blueMetallic = std::make_shared<BrdfShader>("data/blue-metallic-paint.binary", Color(7.0f, 7.0f, 7.0f));
|
||||
auto darkRed = std::make_shared<BrdfShader>("data/dark-red-paint.binary", Color(7.0f, 7.0f, 7.0f));
|
||||
auto blueMetallic = std::make_shared<BrdfShader>("../data/blue-metallic-paint.binary", Color(7.0f, 7.0f, 7.0f));
|
||||
auto darkRed = std::make_shared<BrdfShader>("../data/dark-red-paint.binary", Color(7.0f, 7.0f, 7.0f));
|
||||
|
||||
// DOF Shader
|
||||
bool dofShader = true;
|
||||
|
||||
|
||||
// Set up the walls
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), mirror));
|
||||
|
||||
scene.add(std::make_shared<InfinitePlane>(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), mirror));
|
||||
|
@ -48,27 +61,34 @@ int main() {
|
|||
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, 0.0f, 0.0f), 1.0f, blueMetallic));
|
||||
scene.add(std::make_shared<Sphere>(Vector3d(0.0f, 2.0f, 0.0f), 1.0f, orange));
|
||||
scene.add(std::make_shared<Sphere>(Vector3d(3.0f, 0.0f, 0.0f), 1.0f, darkRed));
|
||||
scene.add(std::make_shared<Sphere>(Vector3d(-3.0f, -3.3f, -4.0f), 1.0f, mirror));
|
||||
|
||||
// Add the teapot
|
||||
auto teapot = std::make_shared<ObjModel>(gold);
|
||||
teapot->loadObj("data/teapot.obj", Vector3d(3.0f, 3.0f, 3.0f), Vector3d(0.0f, -5.0f, 0.0f));
|
||||
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<AmbientLight>(0.15f));
|
||||
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 4.0f, -4.0f), 15.0f));
|
||||
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 4.0f, 4.0f), 15.0f));
|
||||
//scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 4.0f, -4.0f), 15.0f));
|
||||
scene.add(std::make_shared<PointLight>(Vector3d(0.0f, 2.5f, -4.0f), 7.0f));
|
||||
|
||||
|
||||
// Set up the camera
|
||||
PerspectiveCamera camera;
|
||||
camera.setFovAngle(90.0f);
|
||||
camera.setPosition(Vector3d(0.0f, 0.0f, -10.0f));
|
||||
camera.setForwardDirection(Vector3d(0.0f, 0.0f, 1.0f));
|
||||
camera.setUpDirection(Vector3d(0.0f, 1.0f, 0.0f));
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
88
post_processing/bloom.cpp
Normal file
88
post_processing/bloom.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
|
||||
#include <iostream>
|
||||
#include "bloom.h"
|
||||
|
||||
Bloom::Bloom(CImg<float> image) : image(image) {}
|
||||
|
||||
|
||||
CImg<float> Bloom::bloom(float threshold, int kernelSize, float sigma, float intensity) {
|
||||
// Apply threshold to image
|
||||
//CImg<float> brightPixels = image_.get_threshold(threshold);
|
||||
//brightPixels.save("brightpixels.png");
|
||||
|
||||
// Apply gaussian blur to bright pixels
|
||||
CImg<float> kernel = computeGaussianKernel(kernelSize, sigma);
|
||||
CImg<float> 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;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void Bloom::gaussianBlur(int kernelSize, float sigma) {
|
||||
CImg<float> kernel = computeGaussianKernel(kernelSize, sigma);
|
||||
image = convolution(image, kernel);
|
||||
}
|
||||
|
||||
// Function to compute Gaussian kernel
|
||||
CImg<float> Bloom::computeGaussianKernel(int kernelSize, float sigma) {
|
||||
// Create kernel
|
||||
CImg<float> 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<float> Bloom::convolution(CImg<float> &img, CImg<float> &kernel) {
|
||||
int kernelSize = kernel.width();
|
||||
int imgRows = img.height();
|
||||
int imgCols = img.width();
|
||||
CImg<float> 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 Bloom::scaleBrightness(float scale) {
|
||||
image *= scale;
|
||||
}
|
27
post_processing/bloom.h
Normal file
27
post_processing/bloom.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
#ifndef CG1_TRACER_BLOOM_H
|
||||
#define CG1_TRACER_BLOOM_H
|
||||
|
||||
#include "common/texture.h"
|
||||
#include "common/vector3d.h"
|
||||
|
||||
class Bloom {
|
||||
|
||||
public:
|
||||
Bloom(CImg<float> image);
|
||||
CImg<float> bloom(float threshold, int kernelSize, float sigma, float intensity);
|
||||
|
||||
private:
|
||||
void scaleBrightness(float scale);
|
||||
void gaussianBlur(int kernelSize, float sigma);
|
||||
|
||||
CImg<float> convolution(CImg<float> &img, CImg<float> &kernel);
|
||||
CImg<float> computeGaussianKernel(int kernelSize, float sigma);
|
||||
|
||||
|
||||
|
||||
CImg<float> image;
|
||||
};
|
||||
|
||||
|
||||
#endif //CG1_TRACER_BLOOM_H
|
124
renderer/depthoffieldrenderer.cpp
Normal file
124
renderer/depthoffieldrenderer.cpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "depthoffieldrenderer.h"
|
||||
#include <iomanip>
|
||||
#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<float> 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<int> *k, int const stepSize) {
|
||||
float const aspectRatio = static_cast<float>(height) / width;
|
||||
for (int y = heightOffset; y < height; y += heightStep) {
|
||||
for (int x = widthOffset; x < width; x += widthStep) {
|
||||
Ray ray = camera->createRay((static_cast<float>(x) / width * 2 - 1), -(static_cast<float>(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<int> 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<std::thread> 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<std::chrono::duration<double>>(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;
|
||||
}
|
35
renderer/depthoffieldrenderer.h
Normal file
35
renderer/depthoffieldrenderer.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef DEPTHOFFIELDSHADER_H
|
||||
#define DEPTHOFFIELDSHADER_H
|
||||
|
||||
#include "camera/camera.h"
|
||||
#include <random>
|
||||
#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<int> *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
|
|
@ -5,6 +5,7 @@
|
|||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#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<int> *k, int const stepSize) {
|
||||
float const aspectRatio = static_cast<float>(height) / width;
|
||||
|
@ -73,6 +74,13 @@ 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
|
||||
|
||||
image.save("original.png");
|
||||
|
||||
Bloom bloomEffect = Bloom(image.getImage());
|
||||
image.setTexture(bloomEffect.bloom(0.55f, 5, 10.0f, 0.06f));
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
|
@ -3,11 +3,12 @@
|
|||
|
||||
#include <atomic>
|
||||
#include "renderer/renderer.h"
|
||||
#include <renderer/depthoffieldrenderer.h>
|
||||
|
||||
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<int> *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<int> *k,
|
||||
const int stepSize);
|
||||
|
||||
public:
|
||||
// Constructor / Destructor
|
||||
|
|
Loading…
Reference in a new issue