cloudy-raytracer/post-processing/bloomshader.cpp

89 lines
2.5 KiB
C++
Raw Normal View History

2023-01-24 13:32:19 +01:00
#include <iostream>
#include "bloomshader.h"
2023-01-25 10:20:27 +01:00
Bloomshader::Bloomshader(CImg<float> image) : image(image) {}
CImg<float> Bloomshader::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;
2023-01-24 13:32:19 +01:00
}
return image;
}
2023-01-25 10:20:27 +01:00
void Bloomshader::gaussianBlur(int kernelSize, float sigma) {
CImg<float> kernel = computeGaussianKernel(kernelSize, sigma);
image = convolution(image, kernel);
}
// Function to compute Gaussian kernel
CImg<float> Bloomshader::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;
2023-01-24 13:32:19 +01:00
2023-01-25 10:20:27 +01:00
return kernel;
}
2023-01-24 13:32:19 +01:00
2023-01-25 10:20:27 +01:00
// Function to perform convolution
CImg<float> Bloomshader::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;
2023-01-24 13:32:19 +01:00
2023-01-25 10:20:27 +01:00
// 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);
}
2023-01-24 13:32:19 +01:00
2023-01-25 10:20:27 +01:00
}
2023-01-24 13:32:19 +01:00
}
2023-01-25 10:20:27 +01:00
result(i, j, 0, c) = sum;
2023-01-24 13:32:19 +01:00
}
2023-01-25 10:20:27 +01:00
return result;
2023-01-24 13:32:19 +01:00
}
2023-01-25 10:20:27 +01:00
void Bloomshader::scaleBrightness(float scale) {
image *= scale;
2023-01-24 13:32:19 +01:00
}