Add Framwork for Assignment 3

This commit is contained in:
hal8174 2024-06-13 13:53:07 +02:00
parent a2d7f5c414
commit c864d2a42f
14 changed files with 50048 additions and 48111 deletions

0
Framework/external/imgui/backends/vulkan/generate_spv.sh vendored Executable file → Normal file
View file

View file

@ -38,6 +38,7 @@
#include "camera.hpp" #include "camera.hpp"
#include "ray.hpp" #include "ray.hpp"
#include "random_sampler.hpp" #include "random_sampler.hpp"
#include "random_sampler_wrapper.hpp"
class Application { class Application {
public: public:
@ -48,15 +49,16 @@ public:
void run(); void run();
protected: protected:
virtual Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) = 0; virtual Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler) = 0;
void deviceRender(const ISPCCamera& camera); void deviceRender(const ISPCCamera& camera);
virtual void drawGUI() = 0; virtual void drawGUI() {
}
virtual void initScene() = 0; virtual void initScene() = 0;
void render(int* pixels, int width, int height, float time, const ISPCCamera& camera); virtual void render(int* pixels, int width, int height, float time, const ISPCCamera& camera);
void renderTile(int taskIndex, int threadIndex, int* pixels, unsigned int width, void renderTile(int taskIndex, int threadIndex, int* pixels, unsigned int width,
unsigned int height, unsigned int height,
@ -90,6 +92,13 @@ protected:
void scrollCallback(GLFWwindow*, double xoffset, double yoffset); void scrollCallback(GLFWwindow*, double xoffset, double yoffset);
// it is invoked when the scene changes
virtual void resetRender() {
data.accu_count = 0;
data.film.clear();
}
void initRayStats(); void initRayStats();
int64_t getNumRays(); int64_t getNumRays();
@ -130,7 +139,7 @@ protected:
double clickX = 0; double clickX = 0;
double clickY = 0; double clickY = 0;
float speed = 400; float speed = 1;
Vec3f moveDelta = {0, 0, 0}; Vec3f moveDelta = {0, 0, 0};
RayStats* g_stats = nullptr; RayStats* g_stats = nullptr;

View file

@ -0,0 +1,118 @@
#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"
// https://github.com/mmp/pbrt-v3/blob/master/src/core/pbrt.h#L403
template <typename Predicate>
int FindInterval(int size, const Predicate& pred) {
int first = 0, len = size;
while (len > 0) {
int half = len >> 1, middle = first + half;
// Bisect range based on value of _pred_ at _middle_
if (pred(middle)) {
first = middle + 1;
len -= half + 1;
}
else
len = half;
}
return clamp(first - 1, 0, size - 2);
}
struct Distribution1D {
Distribution1D(){}
// Distribution1D Public Methods
Distribution1D(const float* f, int n) : func(f, f + n), cdf(n + 1) {
// Compute integral of step function at $x_i$
cdf[0] = 0;
for (int i = 1; i < n + 1; ++i) cdf[i] = cdf[i - 1] + func[i - 1] / n;
// Transform step function integral into CDF
funcInt = cdf[n];
if (funcInt == 0) {
for (int i = 1; i < n + 1; ++i) cdf[i] = float(i) / float(n);
}
else {
for (int i = 1; i < n + 1; ++i) cdf[i] /= funcInt;
}
}
int Count() const { return (int)func.size(); }
float SampleContinuous(float u, float* pdf, int* off = nullptr) const {
// Find surrounding CDF segments and _offset_
int offset = FindInterval((int)cdf.size(),
[&](int index) { return cdf[index] <= u; });
if (off) *off = offset;
// Compute offset along CDF segment
float du = u - cdf[offset];
if ((cdf[offset + 1] - cdf[offset]) > 0) {
du /= (cdf[offset + 1] - cdf[offset]);
}
assert(!std::isnan(du));
// Compute PDF for sampled offset
if (pdf) *pdf = (funcInt > 0) ? func[offset] / funcInt : 0;
// Return $x\in{}[0,1)$ corresponding to sample
return (offset + du) / Count();
}
int SampleDiscrete(float u, float* pdf = nullptr,
float* uRemapped = nullptr) const {
// Find surrounding CDF segments and _offset_
int offset = FindInterval((int)cdf.size(),
[&](int index) { return cdf[index] <= u; });
if (pdf) *pdf = (funcInt > 0) ? func[offset] / (funcInt * Count()) : 0;
if (uRemapped)
*uRemapped = (u - cdf[offset]) / (cdf[offset + 1] - cdf[offset]);
if (uRemapped) assert(*uRemapped >= 0.f && *uRemapped <= 1.f);
return offset;
}
float DiscretePDF(int index) const {
assert(index >= 0 && index < Count());
return func[index] / (funcInt * Count());
}
// Distribution1D Public Data
std::vector<float> func, cdf;
float funcInt;
};

185
Framework/include/film.hpp Normal file
View file

@ -0,0 +1,185 @@
#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;
};

View file

@ -9,6 +9,7 @@
#include <algorithms/parallel_for.h> #include <algorithms/parallel_for.h>
#include <scenegraph/scenegraph.h> #include <scenegraph/scenegraph.h>
#include <scenegraph/grid.h> #include <scenegraph/grid.h>
#include "film.hpp"
// #include <lights/light.h> // #include <lights/light.h>
#include "scene.hpp" #include "scene.hpp"
@ -23,6 +24,7 @@ struct Sample {
embree::Vec3fa Ns; embree::Vec3fa Ns;
}; };
struct Data { struct Data {
RenderScene* scene; RenderScene* scene;
Grid* densityGrid; Grid* densityGrid;
@ -31,25 +33,23 @@ struct Data {
int max_path_length; int max_path_length;
/* accumulation buffer */ /* accumulation buffer */
embree::Vec3ff* accu; Film film;
unsigned int accu_width;
unsigned int accu_height;
unsigned int accu_count; unsigned int accu_count;
unsigned int frame_count = 0;
RTCScene g_scene; RTCScene g_scene;
}; };
inline void Data_Constructor(Data* This, int spp, int max_path_length) { inline void Data_Constructor(Data* This, int spp, int max_path_length) {
This->g_scene = nullptr; This->g_scene = nullptr;
This->scene = nullptr; This->scene = nullptr;
This->accu = nullptr;
This->spp = spp; This->spp = spp;
This->max_path_length = max_path_length; This->max_path_length = max_path_length;
This->accu = nullptr;
This->accu_width = 0;
This->accu_height = 0;
This->accu_count = 0; This->accu_count = 0;
} }

View file

@ -0,0 +1,37 @@
#pragma once
#include <random_sampler.hpp>
namespace embree {
// Wrapper class
class RandomSamplerWrapper {
public:
RandomSampler sampler;
virtual void init(int id) {
RandomSampler_init(sampler, id);
}
virtual void init(int pixelID, int sampleID) {
RandomSampler_init(sampler, pixelID, sampleID);
}
virtual void init(int x, int y, int sampleID) {
RandomSampler_init(sampler, x, y, sampleID);
}
virtual float get1D() {
return RandomSampler_get1D(sampler);
}
virtual Vec2f get2D() {
return RandomSampler_get2D(sampler);
}
virtual Vec3fa get3D() {
return RandomSampler_get3D(sampler);
}
};
}

View file

@ -107,6 +107,37 @@ inline Vec3fa uniformSampleCone(const float cosAngle, const Vec2f &s)
return cartesian(phi, cosTheta); return cartesian(phi, cosTheta);
} }
inline float erfInv(float x) {
float w, p;
x = clamp(x, -.99999f, .99999f);
w = -std::log((1 - x) * (1 + x));
if (w < 5) {
w = w - 2.5f;
p = 2.81022636e-08f;
p = 3.43273939e-07f + p * w;
p = -3.5233877e-06f + p * w;
p = -4.39150654e-06f + p * w;
p = 0.00021858087f + p * w;
p = -0.00125372503f + p * w;
p = -0.00417768164f + p * w;
p = 0.246640727f + p * w;
p = 1.50140941f + p * w;
}
else {
w = std::sqrt(w) - 3;
p = -0.000200214257f;
p = 0.000100950558f + p * w;
p = 0.00134934322f + p * w;
p = -0.00367342844f + p * w;
p = 0.00573950773f + p * w;
p = -0.0076224613f + p * w;
p = 0.00943887047f + p * w;
p = 1.00167406f + p * w;
p = 2.83297682f + p * w;
}
return p * x;
}
inline float uniformSampleConePDF(const float cosAngle) inline float uniformSampleConePDF(const float cosAngle)
{ {
return rcp(float(two_pi)*(1.0f - cosAngle)); return rcp(float(two_pi)*(1.0f - cosAngle));

View file

@ -54,11 +54,6 @@ namespace embree
data.resize(res.x * res.y * res.z); data.resize(res.x * res.y * res.z);
file.read(reinterpret_cast<char*>(data.data()), data.size() * sizeof(float)); file.read(reinterpret_cast<char*>(data.data()), data.size() * sizeof(float));
float max = 0;
for (size_t i = 0; i < res.x * res.y * res.z; i++) {
max = std::max(data[i], max);
}
printf("max:\t%f\n", max);
file.close(); file.close();
} }

38
Framework/scenes/box2.obj Normal file
View file

@ -0,0 +1,38 @@
# Blender 4.1.1
# www.blender.org
o box
v -0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 0.500000 0.500000
v 0.500000 -0.500000 -0.500000
v 0.500000 0.500000 -0.500000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/8/4 6/7/4 2/9/4 1/10/4
f 3/11/5 7/6/5 5/8/5 1/12/5
f 8/5/6 4/13/6 2/14/6 6/7/6

View file

@ -0,0 +1,29 @@
# Blender 4.1.1 MTL File: 'None'
# www.blender.org
newmtl copper
Ns 196.513947
Ka 1.000000 1.000000 1.000000
Kd 0.800416 0.334137 0.043725
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 2.000000
d 1.000000
type metal
illum 3
newmtl white
Ka 0 0 0
Kd 1 1 1
Ks 0 0 0
newmtl oldwhite
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,32 @@
newmtl white # Blender 4.1.1 MTL File: 'None'
Ka 0 0 0 # www.blender.org
Kd 1 1 1
Ks 0 0 0
newmtl green
Ka 0 0 0
Kd 0 1 0
Ks 0 0 0
newmtl blue newmtl blue
Ka 0 0 0 Ns 0.000000
Kd 0 0 1 Ka 1.000000 1.000000 1.000000
Ks 0 0 0 Kd 0.000000 0.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
newmtl green
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 1.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
newmtl white
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Kd 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1

File diff suppressed because it is too large Load diff

View file

@ -185,14 +185,8 @@ void Application::deviceRender(const ISPCCamera& camera) {
} }
/* create accumulator */ /* create accumulator */
if (data.accu_width != width || data.accu_height != height) { if (data.film.width != width || data.film.height != height) {
alignedUSMFree(data.accu); data.film.init(width, height);
data.accu = (Vec3ff *) alignedUSMMalloc((width * height) * sizeof(Vec3ff), 16,
EMBREE_USM_SHARED_DEVICE_READ_WRITE);
data.accu_width = width;
data.accu_height = height;
for (unsigned int i = 0; i < width * height; i++)
data.accu[i] = Vec3ff(0.0f);
} }
/* reset accumulator */ /* reset accumulator */
@ -208,13 +202,14 @@ void Application::deviceRender(const ISPCCamera& camera) {
g_accu_p = camera.xfm.p; g_accu_p = camera.xfm.p;
if (camera_changed) { if (camera_changed) {
data.accu_count = 0; resetRender();
for (unsigned int i = 0; i < width * height; i++)
data.accu[i] = Vec3ff(0.0f);
} else } else
data.accu_count++; data.accu_count++;
data.frame_count++;
} }
void Application::renderInteractive() { void Application::renderInteractive() {
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
glfwPollEvents(); glfwPollEvents();
@ -243,6 +238,8 @@ void Application::displayFunc() {
/* render image using ISPC */ /* render image using ISPC */
initRayStats(); initRayStats();
render((int *) pixels, width, height, time, ispccamera); render((int *) pixels, width, height, time, ispccamera);
data.film.writeToFramebuffer(pixels);
double dt0 = getSeconds() - t0; double dt0 = getSeconds() - t0;
if (ispccamera.render_time != 0.0) dt0 = ispccamera.render_time; if (ispccamera.render_time != 0.0) dt0 = ispccamera.render_time;
avg_render_time.add(dt0); avg_render_time.add(dt0);
@ -270,6 +267,10 @@ void Application::displayFunc() {
ImGui::Checkbox("Accumulate", &g_accumulate); ImGui::Checkbox("Accumulate", &g_accumulate);
ImGui::InputInt("SPP", &data.spp); ImGui::InputInt("SPP", &data.spp);
if (ImGui::Button("Reset")) {
resetRender();
};
double render_dt = avg_render_time.get(); double render_dt = avg_render_time.get();
double render_fps = render_dt != 0.0 ? 1.0f / render_dt : 0.0; double render_fps = render_dt != 0.0 ? 1.0f / render_dt : 0.0;
ImGui::Text("Render: %3.2f fps", render_fps); ImGui::Text("Render: %3.2f fps", render_fps);
@ -332,27 +333,22 @@ void Application::renderTile(int taskIndex, int threadIndex, int* pixels, const
for (unsigned int y = y0; y < y1; y++) for (unsigned int y = y0; y < y1; y++)
for(unsigned int x = x0; x < x1; x++) { for(unsigned int x = x0; x < x1; x++) {
RandomSampler sampler; RandomSamplerWrapper sampler;
Vec3fa L = Vec3fa(0.0f); Vec3fa L = Vec3fa(0.0f);
for (int i=0; i<data.spp; i++) for (int i=0; i<data.spp; i++)
{ {
RandomSampler_init(sampler, x, y, data.accu_count*data.spp+i); sampler.init(x, y, (data.frame_count) * data.spp + i);
/* calculate pixel color */ /* calculate pixel color */
float fx = x + RandomSampler_get1D(sampler); float fx = x + sampler.get1D();
float fy = y + RandomSampler_get1D(sampler); float fy = y + sampler.get1D();
L = L + renderPixel(fx,fy,camera,g_stats[threadIndex],sampler); L = L + renderPixel(fx,fy,camera,g_stats[threadIndex],sampler);
} }
L = L/(float)data.spp; L = L/(float)data.spp;
/* write color to framebuffer */ /* write color to framebuffer */
Vec3ff accu_color = data.accu[y*width+x] + Vec3ff(L.x,L.y,L.z,1.0f); data.accu[y*width+x] = accu_color; data.film.addSplat(x, y, L);
float f = rcp(max(0.001f,accu_color.w));
unsigned int r = (unsigned int) (255.01f * clamp(accu_color.x*f,0.0f,1.0f));
unsigned int g = (unsigned int) (255.01f * clamp(accu_color.y*f,0.0f,1.0f));
unsigned int b = (unsigned int) (255.01f * clamp(accu_color.z*f,0.0f,1.0f));
pixels[y*width+x] = (b << 16) + (g << 8) + r;
} }
} }