rendering-in-cgi/Framework/include/film.hpp

185 lines
No EOL
3.9 KiB
C++

#pragma once
#include <sys/platform.h>
#include <sys/sysinfo.h>
#include <sys/alloc.h>
#include <sys/ref.h>
#include <sys/vector.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <math/bbox.h>
#include <math/lbbox.h>
#include <math/affinespace.h>
#include <sys/filename.h>
#include <sys/estring.h>
#include <lexers/tokenstream.h>
#include <lexers/streamfilters.h>
#include <lexers/parsestream.h>
#include <atomic>
#include <sstream>
#include <vector>
#include <memory>
#include <map>
#include <set>
#include <deque>
#include "helper.hpp"
#include <sys/sysinfo.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include "camera.hpp"
#include "ray.hpp"
#include "random_sampler.hpp"
#include "random_sampler_wrapper.hpp"
inline unsigned int packColor(unsigned int r, unsigned int g, unsigned int b) {
return (b << 16) + (g << 8) + r;
}
#include <atomic>
// AtomicFloat Class
class AtomicFloat {
public:
// AtomicFloat Public Methods
explicit AtomicFloat(float v = 0.0f) {
bits = floatToBits(v);
}
operator float() const {
return bitsToFloat(bits);
}
float operator=(float v) {
bits = floatToBits(v);
return v;
}
void add(float v) {
uint32_t oldBits = bits, newBits;
do {
newBits = floatToBits(bitsToFloat(oldBits) + v);
} while (!bits.compare_exchange_weak(oldBits, newBits));
}
private:
// AtomicFloat Private Data
std::atomic<uint32_t> bits;
// Helper functions to convert between float and uint32_t
static uint32_t floatToBits(float f) {
uint32_t u;
memcpy(&u, &f, sizeof(uint32_t));
return u;
}
static float bitsToFloat(uint32_t u) {
float f;
memcpy(&f, &u, sizeof(uint32_t));
return f;
}
};
class Film {
public:
Film() {
}
Film(unsigned int width, unsigned int height)
{
init(width, height);
}
void init(unsigned int w, unsigned int h) {
width = w;
height = h;
size_t size = width * height;
accu_x = std::make_unique<AtomicFloat[]>(size);
accu_y = std::make_unique<AtomicFloat[]>(size);
accu_z = std::make_unique<AtomicFloat[]>(size);
splat_count = std::make_unique<std::atomic<unsigned int>[]>(size);
clear();
}
// atomic safe
void addSplat(int x, int y, const Vec3fa& value) {
size_t index = y * width + x;
accu_x[index].add(value.x);
accu_y[index].add(value.y);
accu_z[index].add(value.z);
if(count)
splat_count[index].fetch_add(1, std::memory_order_relaxed);
}
void writeToFramebuffer(unsigned int* pixels) {
parallel_for(size_t(0), size_t(width * height), [&](const range<size_t>& range) {
for (size_t i = range.begin(); i < range.end(); ++i) {
pixels[i] = getPackedColor(i);
}
});
}
unsigned int getPackedColor(size_t index) const {
float divider = 1.0;
if (count) {
unsigned int count = splat_count[index].load(std::memory_order_relaxed);
if (count == 0) return 0; // Return black if no splats
divider = 1.0 / count;
}
float accu_x_val = accu_x[index] *divider* scalar;
float accu_y_val = accu_y[index] * divider* scalar;
float accu_z_val = accu_z[index] * divider* scalar;
unsigned int r = static_cast<unsigned int>(255.01f * clamp(accu_x_val, 0.0f, 1.0f));
unsigned int g = static_cast<unsigned int>(255.01f * clamp(accu_y_val, 0.0f, 1.0f));
unsigned int b = static_cast<unsigned int>(255.01f * clamp(accu_z_val, 0.0f, 1.0f));
return packColor(r, g, b);
}
unsigned int getPackedColor(int x, int y) const {
return getPackedColor(y * width + x);
}
void clear() {
parallel_for(size_t(0), size_t(width * height), [&](const range<size_t>& range) {
for (size_t i = range.begin(); i < range.end(); ++i) {
accu_x[i] = 0.0f;
accu_y[i] = 0.0f;
accu_z[i] = 0.0f;
splat_count[i].store(0, std::memory_order_relaxed);
}
});
}
float scalar = 1.0;
unsigned int width, height;
bool count = true;
private:
std::unique_ptr<AtomicFloat[]> accu_x, accu_y, accu_z;
std::unique_ptr<std::atomic<unsigned int>[]> splat_count;
};