Compare commits
2 commits
a2d7f5c414
...
319802d895
| Author | SHA1 | Date | |
|---|---|---|---|
| 319802d895 | |||
| c864d2a42f |
21 changed files with 50815 additions and 48113 deletions
147
Assignments/Assignment3/Application3.cpp
Normal file
147
Assignments/Assignment3/Application3.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include "Application3.h"
|
||||||
|
|
||||||
|
void Application3::initScene() {
|
||||||
|
Data_Constructor(&data, 1, 8);
|
||||||
|
|
||||||
|
/* select scene here */
|
||||||
|
//standardScene();
|
||||||
|
causticScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application3::standardScene() {
|
||||||
|
FileName file = workingDir + FileName("Framework/scenes/cornell_box.obj");
|
||||||
|
|
||||||
|
/* set default camera */
|
||||||
|
camera.from = Vec3fa(278, 273, -800);
|
||||||
|
camera.to = Vec3fa(278, 273, 0);
|
||||||
|
|
||||||
|
Ref<SceneGraph::GroupNode> sceneGraph = loadOBJ(file, false).cast<SceneGraph::GroupNode>();
|
||||||
|
|
||||||
|
auto light = new SceneGraph::QuadLightMesh(Vec3fa(343.0, 548.0, 227.0), Vec3fa(213.0, 548.0, 332.0),
|
||||||
|
Vec3fa(343.0, 548.0, 332.0),
|
||||||
|
Vec3fa(213.0, 548.0, 227.0), Vec3fa(25, 25, 25));
|
||||||
|
sceneGraph->add(light);
|
||||||
|
|
||||||
|
Ref<SceneGraph::GroupNode> flattened_scene = SceneGraph::flatten(sceneGraph, SceneGraph::INSTANCING_NONE);
|
||||||
|
Scene* scene = new Scene;
|
||||||
|
scene->add(flattened_scene);
|
||||||
|
sceneGraph = nullptr;
|
||||||
|
flattened_scene = nullptr;
|
||||||
|
|
||||||
|
auto renderScene = new RenderScene(g_device, scene);
|
||||||
|
g_render_scene = renderScene;
|
||||||
|
data.scene = renderScene;
|
||||||
|
scene = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application3::causticScene() {
|
||||||
|
FileName file = workingDir + FileName("Framework/scenes/caustics/ring.obj");
|
||||||
|
|
||||||
|
/* set default camera */
|
||||||
|
camera.from = Vec3fa(1, 2, 1);
|
||||||
|
camera.to = Vec3fa(0, 0, 0);
|
||||||
|
camera.fov = 60;
|
||||||
|
|
||||||
|
Ref<SceneGraph::GroupNode> sceneGraph = loadOBJ(file, false).cast<SceneGraph::GroupNode>();
|
||||||
|
|
||||||
|
auto light = new SceneGraph::QuadLightMesh(Vec3fa(0.1, 1.0, 2.0), Vec3fa(-0.1, 1.2, 2.0),
|
||||||
|
Vec3fa(-0.1, 1.0, 2.0), Vec3fa(0.1, 1.2, 2.0),
|
||||||
|
Vec3fa(50, 50, 50));
|
||||||
|
|
||||||
|
sceneGraph->add(light);
|
||||||
|
|
||||||
|
|
||||||
|
Ref<SceneGraph::GroupNode> flattened_scene = SceneGraph::flatten(sceneGraph, SceneGraph::INSTANCING_NONE);
|
||||||
|
Scene* scene = new Scene;
|
||||||
|
scene->add(flattened_scene);
|
||||||
|
sceneGraph = nullptr;
|
||||||
|
flattened_scene = nullptr;
|
||||||
|
|
||||||
|
auto renderScene = new RenderScene(g_device, scene);
|
||||||
|
g_render_scene = renderScene;
|
||||||
|
data.scene = renderScene;
|
||||||
|
scene = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
IMPORTANT: use your own path tracing implementation from the 1st assignment!!
|
||||||
|
the only change that we made was introduction of the RandomSamplerWrapper. It wrappes the sampling routines, so you could introduce a new sampler for Metropolis Light Transport and by overwriting RandomSamplerWrapper methods: get1D(), get2D()...
|
||||||
|
also the drawGUI() function now invokes ApplicationIntegrator::drawGUI();
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* task that renders a single screen tile */
|
||||||
|
Vec3fa Application3::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler) {
|
||||||
|
/* radiance accumulator and weight */
|
||||||
|
Vec3fa L = Vec3fa(0.0f);
|
||||||
|
Vec3fa Lw = Vec3fa(1.0f);
|
||||||
|
|
||||||
|
/* initialize ray */
|
||||||
|
Ray ray(Vec3fa(camera.xfm.p), Vec3fa(normalize(x * camera.xfm.l.vx + y * camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f,
|
||||||
|
inf);
|
||||||
|
|
||||||
|
/* intersect ray with scene */
|
||||||
|
RTCIntersectArguments iargs;
|
||||||
|
rtcInitIntersectArguments(&iargs);
|
||||||
|
iargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
||||||
|
rtcIntersect1(data.g_scene, RTCRayHit_(ray), &iargs);
|
||||||
|
RayStats_addRay(stats);
|
||||||
|
|
||||||
|
const Vec3fa wo = neg(ray.dir);
|
||||||
|
|
||||||
|
/* shade pixels */
|
||||||
|
if (ray.geomID != RTC_INVALID_GEOMETRY_ID) {
|
||||||
|
Vec3fa Ns = normalize(ray.Ng);
|
||||||
|
Sample sample;
|
||||||
|
sample.P = ray.org + ray.tfar * ray.dir;
|
||||||
|
sample.Ng = ray.Ng;
|
||||||
|
sample.Ns = Ns;
|
||||||
|
unsigned matId = data.scene->geometries[ray.geomID]->materialID;
|
||||||
|
unsigned lightID = data.scene->geometries[ray.geomID]->lightID;
|
||||||
|
|
||||||
|
if (lightID != unsigned(-1)) {
|
||||||
|
const Light* l = data.scene->lights[lightID];
|
||||||
|
Light_EvalRes evalRes = Lights_eval(l, sample, -wo);
|
||||||
|
|
||||||
|
L += evalRes.value;
|
||||||
|
} else {
|
||||||
|
sample.Ng = face_forward(ray.dir, normalize(sample.Ng));
|
||||||
|
sample.Ns = face_forward(ray.dir, normalize(sample.Ns));
|
||||||
|
|
||||||
|
/* calculate BRDF */
|
||||||
|
BRDF brdf;
|
||||||
|
std::vector<Material *> material_array = data.scene->materials;
|
||||||
|
Material__preprocess(material_array, matId, brdf, wo, sample);
|
||||||
|
|
||||||
|
/* sample BRDF at hit point */
|
||||||
|
Sample3f wi1;
|
||||||
|
Material__sample(material_array, matId, brdf, Lw, wo, sample, wi1, sampler.get2D());
|
||||||
|
|
||||||
|
int id = (int)(sampler.get1D()* data.scene->lights.size());
|
||||||
|
if (id == data.scene->lights.size())
|
||||||
|
id = data.scene->lights.size() - 1;
|
||||||
|
const Light* l = data.scene->lights[id];
|
||||||
|
|
||||||
|
Light_SampleRes ls = Lights_sample(l, sample, sampler.get2D());
|
||||||
|
|
||||||
|
Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir);
|
||||||
|
|
||||||
|
/* initialize shadow ray */
|
||||||
|
Ray shadow(sample.P, ls.dir, 0.001f, ls.dist-0.001f, 0.0f);
|
||||||
|
|
||||||
|
/* trace shadow ray */
|
||||||
|
RTCOccludedArguments sargs;
|
||||||
|
rtcInitOccludedArguments(&sargs);
|
||||||
|
sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
||||||
|
rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs);
|
||||||
|
RayStats_addShadowRay(stats);
|
||||||
|
|
||||||
|
/* add light contribution if not occluded */
|
||||||
|
if (shadow.tfar >= 0.0f) {
|
||||||
|
L += diffuse * ls.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return L;
|
||||||
|
}
|
||||||
26
Assignments/Assignment3/Application3.h
Normal file
26
Assignments/Assignment3/Application3.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
#include "helper.hpp"
|
||||||
|
#include "application_integrator.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Application3 : public ApplicationIntegrator {
|
||||||
|
public:
|
||||||
|
Application3(int argc, char** argv) : ApplicationIntegrator(argc, argv, "Assignment 3") {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler) override;
|
||||||
|
|
||||||
|
|
||||||
|
void drawGUI() override {
|
||||||
|
ApplicationIntegrator::drawGUI(); // NEW!
|
||||||
|
}
|
||||||
|
|
||||||
|
void initScene() override;
|
||||||
|
|
||||||
|
void standardScene();
|
||||||
|
|
||||||
|
void causticScene();
|
||||||
|
|
||||||
|
float colorLight[3] = {1.0f, 1.0f, 1.0f};
|
||||||
|
};
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
|
||||||
project(Assignment3)
|
project(Assignment3)
|
||||||
|
add_executable(${PROJECT_NAME} "assignment3.cpp"
|
||||||
add_executable(${PROJECT_NAME} "assignment3.cpp")
|
Application3.cpp
|
||||||
|
Application3.h
|
||||||
|
application_integrator.h
|
||||||
|
application_integrator.cpp
|
||||||
|
helper.hpp)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC CGI-framework)
|
target_link_libraries(${PROJECT_NAME} PUBLIC CGI-framework)
|
||||||
|
|
|
||||||
108
Assignments/Assignment3/application_integrator.cpp
Normal file
108
Assignments/Assignment3/application_integrator.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "application_integrator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ApplicationIntegrator::ApplicationIntegrator(int argc, char** argv, const std::string& name):
|
||||||
|
Application(argc, argv, name)
|
||||||
|
{
|
||||||
|
resetRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationIntegrator::drawGUI() {
|
||||||
|
|
||||||
|
bool bDirty = false;
|
||||||
|
|
||||||
|
if (ImGui::Checkbox("Metropolis", &bMetropolis)) {
|
||||||
|
resetRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bDirty) {
|
||||||
|
resetRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline float luminance(Vec3fa v) {
|
||||||
|
return 0.2126f * v.x + 0.7152f * v.y + 0.0722f * v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationIntegrator::resetRender() {
|
||||||
|
Application::resetRender();
|
||||||
|
|
||||||
|
if (bMetropolis) {
|
||||||
|
data.film.count = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data.film.count = true;
|
||||||
|
data.film.scalar = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationIntegrator::render(int* pixels, int width, int height, float time, const ISPCCamera& camera) {
|
||||||
|
deviceRender(camera);
|
||||||
|
|
||||||
|
if (!bMetropolis) {
|
||||||
|
mcRender(pixels, width, height, time, camera);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mltRender(pixels, width, height, time, camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ApplicationIntegrator::mltRender(int* pixels, int width, int height, float time, const ISPCCamera& camera) {
|
||||||
|
|
||||||
|
// data.film.scalar = ... use it for setting up the correct normalization coefficient
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// you may want to use Distribution1D for the bootstrap
|
||||||
|
// d = Distribution1D(float* bis_values, num_bins)
|
||||||
|
// float integral = d.funcInt;
|
||||||
|
// int index_of_the_sampled_bin = d.SampleDiscrete(rng.get1D());
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationIntegrator::mcRender(int* pixels, int width, int height, float time, const ISPCCamera& camera) {
|
||||||
|
const int numTilesX = (width + TILE_SIZE_X - 1) / TILE_SIZE_X;
|
||||||
|
const int numTilesY = (height + TILE_SIZE_Y - 1) / TILE_SIZE_Y;
|
||||||
|
parallel_for(size_t(0), size_t(numTilesX * numTilesY), [&](const range<size_t>& range) {
|
||||||
|
const int threadIndex = (int)TaskScheduler::threadIndex();
|
||||||
|
for (size_t i = range.begin(); i < range.end(); i++)
|
||||||
|
renderTile((int)i, threadIndex, pixels, width, height, time, camera, numTilesX, numTilesY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* renders a single screen tile */
|
||||||
|
void ApplicationIntegrator::mcRenderTile(int taskIndex, int threadIndex, int* pixels, const unsigned int width,
|
||||||
|
const unsigned int height, const float time, const ISPCCamera& camera, const int numTilesX,
|
||||||
|
const int numTilesY) {
|
||||||
|
const unsigned int tileY = taskIndex / numTilesX;
|
||||||
|
const unsigned int tileX = taskIndex - tileY * numTilesX;
|
||||||
|
const unsigned int x0 = tileX * TILE_SIZE_X;
|
||||||
|
const unsigned int x1 = min(x0 + TILE_SIZE_X, width);
|
||||||
|
const unsigned int y0 = tileY * TILE_SIZE_Y;
|
||||||
|
const unsigned int y1 = min(y0 + TILE_SIZE_Y, height);
|
||||||
|
|
||||||
|
for (unsigned int y = y0; y < y1; y++)
|
||||||
|
for (unsigned int x = x0; x < x1; x++) {
|
||||||
|
RandomSamplerWrapper sampler;
|
||||||
|
Vec3fa L = Vec3fa(0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < data.spp; i++)
|
||||||
|
{
|
||||||
|
sampler.init(x, y, (data.frame_count) * data.spp + i);
|
||||||
|
|
||||||
|
/* calculate pixel color */
|
||||||
|
float fx = x + sampler.get1D();
|
||||||
|
float fy = y + sampler.get1D();
|
||||||
|
L = L + renderPixel(fx, fy, camera, g_stats[threadIndex], sampler);
|
||||||
|
}
|
||||||
|
L = L / (float)data.spp;
|
||||||
|
|
||||||
|
/* write color to framebuffer */
|
||||||
|
data.film.addSplat(x, y, L);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Assignments/Assignment3/application_integrator.h
Normal file
31
Assignments/Assignment3/application_integrator.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
#include "helper.hpp"
|
||||||
|
#include "distribution.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationIntegrator: public Application {
|
||||||
|
public:
|
||||||
|
ApplicationIntegrator(int argc, char** argv, const std::string& name);
|
||||||
|
|
||||||
|
virtual ~ApplicationIntegrator() = default;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void render(int* pixels, int width, int height, float time, const ISPCCamera& camera) override;
|
||||||
|
virtual void drawGUI() override;
|
||||||
|
virtual void resetRender() override;
|
||||||
|
|
||||||
|
|
||||||
|
bool bMetropolis = false;
|
||||||
|
|
||||||
|
|
||||||
|
void mltRender(int* pixels, int width, int height, float time, const ISPCCamera& camera);
|
||||||
|
|
||||||
|
void mcRender(int* pixels, int width, int height, float time, const ISPCCamera& camera);
|
||||||
|
|
||||||
|
/* renders a single screen tile */
|
||||||
|
void mcRenderTile(int taskIndex, int threadIndex, int* pixels, const unsigned int width,
|
||||||
|
const unsigned int height, const float time, const ISPCCamera& camera, const int numTilesX,
|
||||||
|
const int numTilesY);
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
|
#include "Application3.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
auto app = new Application3(argc, argv);
|
||||||
|
|
||||||
|
app->run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
444
Assignments/Assignment3/helper.hpp
Normal file
444
Assignments/Assignment3/helper.hpp
Normal file
|
|
@ -0,0 +1,444 @@
|
||||||
|
#pragma once
|
||||||
|
#include <application.h>
|
||||||
|
#include <sampling.hpp>
|
||||||
|
#include <random_sampler_wrapper.hpp>
|
||||||
|
#include <scenegraph/obj_loader.h>
|
||||||
|
|
||||||
|
#include <lights/ambient_light.h>
|
||||||
|
#include <lights/directional_light.h>
|
||||||
|
#include <lights/point_light.h>
|
||||||
|
#include <lights/quad_light.h>
|
||||||
|
#include <lights/spot_light.h>
|
||||||
|
|
||||||
|
using namespace embree;
|
||||||
|
|
||||||
|
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f * dot(V, N) * N - V; }
|
||||||
|
|
||||||
|
inline Vec3fa face_forward(const Vec3fa& dir, const Vec3fa& _Ng) {
|
||||||
|
const Vec3fa Ng = _Ng;
|
||||||
|
return dot(dir, Ng) < 0.0f ? Ng : neg(Ng);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Light_SampleRes Lights_sample(const Light* self,
|
||||||
|
const Sample& sp, /*! point to generate the sample for >*/
|
||||||
|
const Vec2f s) /*! random numbers to generate the sample >*/
|
||||||
|
{
|
||||||
|
LightType ty = self->type;
|
||||||
|
switch (ty) {
|
||||||
|
case LIGHT_AMBIENT: return AmbientLight_sample(self, sp, s);
|
||||||
|
case LIGHT_POINT: return PointLight_sample(self, sp, s);
|
||||||
|
case LIGHT_DIRECTIONAL: return DirectionalLight_sample(self, sp, s);
|
||||||
|
case LIGHT_SPOT: return SpotLight_sample(self, sp, s);
|
||||||
|
case LIGHT_QUAD: return QuadLight_sample(self, sp, s);
|
||||||
|
default: {
|
||||||
|
Light_SampleRes res;
|
||||||
|
res.weight = Vec3fa(0, 0, 0);
|
||||||
|
res.dir = Vec3fa(0, 0, 0);
|
||||||
|
res.dist = 0;
|
||||||
|
res.pdf = inf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Light_EvalRes Lights_eval(const Light* self,
|
||||||
|
const Sample& sp,
|
||||||
|
const Vec3fa& dir) {
|
||||||
|
LightType ty = self->type;
|
||||||
|
switch (ty) {
|
||||||
|
case LIGHT_AMBIENT: return AmbientLight_eval(self, sp, dir);
|
||||||
|
case LIGHT_POINT: return PointLight_eval(self, sp, dir);
|
||||||
|
case LIGHT_DIRECTIONAL: return DirectionalLight_eval(self, sp, dir);
|
||||||
|
case LIGHT_SPOT: return SpotLight_eval(self, sp, dir);
|
||||||
|
case LIGHT_QUAD: return QuadLight_eval(self, sp, dir);
|
||||||
|
default: {
|
||||||
|
Light_EvalRes res;
|
||||||
|
res.value = Vec3fa(0, 0, 0);
|
||||||
|
res.dist = inf;
|
||||||
|
res.pdf = 0.f;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BRDF {
|
||||||
|
float Ns; /*< specular exponent */
|
||||||
|
float Ni; /*< optical density for the surface (index of refraction) */
|
||||||
|
Vec3fa Ka; /*< ambient reflectivity */
|
||||||
|
Vec3fa Kd; /*< diffuse reflectivity */
|
||||||
|
Vec3fa Ks; /*< specular reflectivity */
|
||||||
|
Vec3fa Kt; /*< transmission filter */
|
||||||
|
float dummy[30];
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Lambertian BRDF //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct Lambertian {
|
||||||
|
Vec3fa R;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vec3fa Lambertian__eval(const Lambertian* This,
|
||||||
|
const Vec3fa& wo, const Sample& dg, const Vec3fa& wi) {
|
||||||
|
return This->R * (1.0f / (float) (float(M_PI))) * clamp(dot(wi, dg.Ns));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa Lambertian__sample(const Lambertian* This,
|
||||||
|
const Vec3fa& wo,
|
||||||
|
const Sample& dg,
|
||||||
|
Sample3f& wi,
|
||||||
|
const Vec2f& s) {
|
||||||
|
wi = cosineSampleHemisphere(s.x, s.y, dg.Ns);
|
||||||
|
return Lambertian__eval(This, wo, dg, wi.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Lambertian__Constructor(Lambertian* This, const Vec3fa& R) {
|
||||||
|
This->R = R;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Lambertian make_Lambertian(const Vec3fa& R) {
|
||||||
|
Lambertian v;
|
||||||
|
Lambertian__Constructor(&v, R);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Matte Material //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void MatteMaterial__preprocess(MatteMaterial* material, BRDF& brdf, const Vec3fa& wo, const Sample& sp) {
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa MatteMaterial__eval(MatteMaterial* This, const BRDF& brdf, const Vec3fa& wo, const Sample& sp,
|
||||||
|
const Vec3fa& wi) {
|
||||||
|
Lambertian lambertian = make_Lambertian(Vec3fa((Vec3fa) This->reflectance));
|
||||||
|
return Lambertian__eval(&lambertian, wo, sp, wi);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa MatteMaterial__sample(MatteMaterial* This, const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo,
|
||||||
|
const Sample& sp, Sample3f& wi_o, const Vec2f& s) {
|
||||||
|
Lambertian lambertian = make_Lambertian(Vec3fa((Vec3fa) This->reflectance));
|
||||||
|
return Lambertian__sample(&lambertian, wo, sp, wi_o, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// OBJ Material //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void OBJMaterial__preprocess(OBJMaterial* material, BRDF& brdf, const Vec3fa& wo, const Sample& sp) {
|
||||||
|
float d = material->d;
|
||||||
|
// if (material->map_d) d *= getTextureTexel1f(material->map_d, dg.u, dg.v);
|
||||||
|
brdf.Ka = Vec3fa(material->Ka);
|
||||||
|
//if (material->map_Ka) { brdf.Ka *= material->map_Ka->get(dg.st); }
|
||||||
|
brdf.Kd = d * Vec3fa(material->Kd);
|
||||||
|
// if (material->map_Kd) brdf.Kd = brdf.Kd * getTextureTexel3f(material->map_Kd, dg.u, dg.v);
|
||||||
|
brdf.Ks = d * Vec3fa(material->Ks);
|
||||||
|
//if (material->map_Ks) brdf.Ks *= material->map_Ks->get(dg.st);
|
||||||
|
brdf.Ns = material->Ns;
|
||||||
|
//if (material->map_Ns) { brdf.Ns *= material->map_Ns.get(dg.st); }
|
||||||
|
brdf.Kt = (1.0f - d) * Vec3fa(material->Kt);
|
||||||
|
brdf.Ni = material->Ni;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa OBJMaterial__eval(OBJMaterial* material, const BRDF& brdf, const Vec3fa& wo, const Sample& sp,
|
||||||
|
const Vec3fa& wi) {
|
||||||
|
Vec3fa R = Vec3fa(0.0f);
|
||||||
|
const float Md = max(max(brdf.Kd.x, brdf.Kd.y), brdf.Kd.z);
|
||||||
|
const float Ms = max(max(brdf.Ks.x, brdf.Ks.y), brdf.Ks.z);
|
||||||
|
const float Mt = max(max(brdf.Kt.x, brdf.Kt.y), brdf.Kt.z);
|
||||||
|
if (Md > 0.0f) {
|
||||||
|
R = R + (1.0f / float(M_PI)) * clamp(dot(wi, sp.Ns)) * brdf.Kd;
|
||||||
|
}
|
||||||
|
if (Ms > 0.0f) {
|
||||||
|
const Sample3f refl = make_Sample3f(reflect(wo, sp.Ns), 1.0f);
|
||||||
|
if (dot(refl.v, wi) > 0.0f) {
|
||||||
|
R = R + (brdf.Ns + 2) * float(one_over_two_pi) * powf(max(1e-10f, dot(refl.v, wi)), brdf.Ns) *
|
||||||
|
clamp(dot(wi, sp.Ns)) * brdf.Ks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Mt > 0.0f) {
|
||||||
|
}
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa OBJMaterial__sample(OBJMaterial* material, const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo,
|
||||||
|
const Sample& sp, Sample3f& wi_o, const Vec2f& s) {
|
||||||
|
Vec3fa cd = Vec3fa(0.0f);
|
||||||
|
Sample3f wid = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
if (max(max(brdf.Kd.x, brdf.Kd.y), brdf.Kd.z) > 0.0f) {
|
||||||
|
wid = cosineSampleHemisphere(s.x, s.y, sp.Ns);
|
||||||
|
cd = float(one_over_pi) * clamp(dot(wid.v, sp.Ns)) * brdf.Kd;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3fa cs = Vec3fa(0.0f);
|
||||||
|
Sample3f wis = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
if (max(max(brdf.Ks.x, brdf.Ks.y), brdf.Ks.z) > 0.0f) {
|
||||||
|
const Sample3f refl = make_Sample3f(reflect(wo, sp.Ns), 1.0f);
|
||||||
|
wis.v = powerCosineSampleHemisphere(brdf.Ns, s);
|
||||||
|
wis.pdf = powerCosineSampleHemispherePDF(wis.v, brdf.Ns);
|
||||||
|
wis.v = frame(refl.v) * wis.v;
|
||||||
|
cs = (brdf.Ns + 2) * float(one_over_two_pi) * powf(max(dot(refl.v, wis.v), 1e-10f), brdf.Ns) *
|
||||||
|
clamp(dot(wis.v, sp.Ns)) * brdf.Ks;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3fa ct = Vec3fa(0.0f);
|
||||||
|
Sample3f wit = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
if (max(max(brdf.Kt.x, brdf.Kt.y), brdf.Kt.z) > 0.0f) {
|
||||||
|
wit = make_Sample3f(neg(wo), 1.0f);
|
||||||
|
ct = brdf.Kt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3fa md = Lw * cd / wid.pdf;
|
||||||
|
const Vec3fa ms = Lw * cs / wis.pdf;
|
||||||
|
const Vec3fa mt = Lw * ct / wit.pdf;
|
||||||
|
|
||||||
|
const float Cd = wid.pdf == 0.0f ? 0.0f : max(max(md.x, md.y), md.z);
|
||||||
|
const float Cs = wis.pdf == 0.0f ? 0.0f : max(max(ms.x, ms.y), ms.z);
|
||||||
|
const float Ct = wit.pdf == 0.0f ? 0.0f : max(max(mt.x, mt.y), mt.z);
|
||||||
|
const float C = Cd + Cs + Ct;
|
||||||
|
|
||||||
|
if (C == 0.0f) {
|
||||||
|
wi_o = make_Sample3f(Vec3fa(0, 0, 0), 0);
|
||||||
|
return Vec3fa(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float CPd = Cd / C;
|
||||||
|
const float CPs = Cs / C;
|
||||||
|
const float CPt = Ct / C;
|
||||||
|
|
||||||
|
if (s.x < CPd) {
|
||||||
|
wi_o = make_Sample3f(wid.v, wid.pdf * CPd);
|
||||||
|
return cd;
|
||||||
|
} else if (s.x < CPd + CPs) {
|
||||||
|
wi_o = make_Sample3f(wis.v, wis.pdf * CPs);
|
||||||
|
return cs;
|
||||||
|
} else {
|
||||||
|
wi_o = make_Sample3f(wit.v, wit.pdf * CPt);
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Metal Material //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// =======================================================
|
||||||
|
struct FresnelConductor
|
||||||
|
{
|
||||||
|
Vec3fa eta; //!< Real part of refraction index
|
||||||
|
Vec3fa k; //!< Imaginary part of refraction index
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Vec3fa fresnelConductor(const float cosi, const Vec3fa &eta, const Vec3fa &k)
|
||||||
|
{
|
||||||
|
const Vec3fa tmp = eta * eta + k * k;
|
||||||
|
const Vec3fa Rpar = (tmp * (cosi * cosi) - 2.0f * eta * cosi + Vec3fa(1.0f)) *
|
||||||
|
rcp(tmp * (cosi * cosi) + 2.0f * eta * cosi + Vec3fa(1.0f));
|
||||||
|
const Vec3fa Rper = (tmp - 2.0f * eta * cosi + Vec3fa(cosi * cosi)) *
|
||||||
|
rcp(tmp + 2.0f * eta * cosi + Vec3fa(cosi * cosi));
|
||||||
|
return 0.5f * (Rpar + Rper);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa eval(const FresnelConductor &This, const float cosTheta)
|
||||||
|
{
|
||||||
|
return fresnelConductor(cosTheta, This.eta, This.k);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FresnelConductor make_FresnelConductor(const Vec3fa &eta, const Vec3fa &k)
|
||||||
|
{
|
||||||
|
FresnelConductor m;
|
||||||
|
m.eta = eta;
|
||||||
|
m.k = k;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================
|
||||||
|
struct PowerCosineDistribution
|
||||||
|
{
|
||||||
|
float exp;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline float eval(const PowerCosineDistribution &This, const float cosThetaH)
|
||||||
|
{
|
||||||
|
return (This.exp + 2) * (1.0f / (2.0f * (float(M_PI)))) * powf(fabs(cosThetaH), This.exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sample(const PowerCosineDistribution &This, const Vec3fa &wo, const Vec3fa &N, Sample3f &wi, const Vec2f s)
|
||||||
|
{
|
||||||
|
Vec3fa dir = powerCosineSampleHemisphere(This.exp, s);
|
||||||
|
Sample3f wh;
|
||||||
|
wh.v = frame(N) * dir;
|
||||||
|
wh.pdf = powerCosineSampleHemispherePDF(dir, This.exp);
|
||||||
|
Sample3f r = make_Sample3f(reflect(wo, wh.v), 1.0f);
|
||||||
|
wi = make_Sample3f(r.v, wh.pdf / (4.0f * fabs(dot(wo, wh.v))));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PowerCosineDistribution make_PowerCosineDistribution(const float _exp)
|
||||||
|
{
|
||||||
|
PowerCosineDistribution m;
|
||||||
|
m.exp = _exp;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void MetalMaterial__preprocess(MetalMaterial *material, BRDF &brdf, const Vec3fa &wo, const Sample &sp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa MetalMaterial__eval(MetalMaterial *material, const BRDF &brdf, const Vec3fa &wo, const Sample &sp, const Vec3fa &wi)
|
||||||
|
{
|
||||||
|
const FresnelConductor fresnel = make_FresnelConductor(Vec3fa(material->eta), Vec3fa(material->k));
|
||||||
|
const PowerCosineDistribution distribution = make_PowerCosineDistribution(rcp(material->roughness));
|
||||||
|
|
||||||
|
const float cosThetaO = dot(wo, sp.Ns);
|
||||||
|
const float cosThetaI = dot(wi, sp.Ns);
|
||||||
|
if (cosThetaI <= 0.0f || cosThetaO <= 0.0f)
|
||||||
|
return Vec3fa(0.f);
|
||||||
|
const Vec3fa wh = normalize(wi + wo);
|
||||||
|
const float cosThetaH = dot(wh, sp.Ns);
|
||||||
|
const float cosTheta = dot(wi, wh); // = dot(wo, wh);
|
||||||
|
const Vec3fa F = eval(fresnel, cosTheta);
|
||||||
|
const float D = eval(distribution, cosThetaH);
|
||||||
|
const float G = min(1.0f, min(2.0f * cosThetaH * cosThetaO / cosTheta,
|
||||||
|
2.0f * cosThetaH * cosThetaI / cosTheta));
|
||||||
|
return (Vec3fa(material->reflectance) * F) * D * G * rcp(4.0f * cosThetaO);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa MetalMaterial__sample(MetalMaterial *material, const BRDF &brdf, const Vec3fa &Lw, const Vec3fa &wo, const Sample &sp, Sample3f &wi_o, const Vec2f &s)
|
||||||
|
{
|
||||||
|
const PowerCosineDistribution distribution = make_PowerCosineDistribution(rcp(material->roughness));
|
||||||
|
|
||||||
|
if (dot(wo, sp.Ns) <= 0.0f)
|
||||||
|
{
|
||||||
|
wi_o = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
return Vec3fa(0.f);
|
||||||
|
}
|
||||||
|
sample(distribution, wo, sp.Ns, wi_o, s);
|
||||||
|
if (dot(wi_o.v, sp.Ns) <= 0.0f)
|
||||||
|
{
|
||||||
|
wi_o = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
return Vec3fa(0.f);
|
||||||
|
}
|
||||||
|
return MetalMaterial__eval(material, brdf, wo, sp, wi_o.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ReflectiveMetal Material //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void ReflectiveMetalMaterial__preprocess(ReflectiveMetalMaterial *material, BRDF &brdf, const Vec3fa &wo, const Sample &sp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa ReflectiveMetalMaterial__eval(ReflectiveMetalMaterial *material, const BRDF &brdf, const Vec3fa &wo, const Sample &sp, const Vec3fa &wi)
|
||||||
|
{
|
||||||
|
return Vec3fa(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa ReflectiveMetalMaterial__sample(ReflectiveMetalMaterial *material, const BRDF &brdf, const Vec3fa &Lw, const Vec3fa &wo, const Sample &sp, Sample3f &wi_o, const Vec2f &s)
|
||||||
|
{
|
||||||
|
wi_o = make_Sample3f(reflect(wo,sp.Ns),1.0f);
|
||||||
|
return Vec3fa(material->reflectance) * fresnelConductor(dot(wo,sp.Ns),Vec3fa((Vec3fa)material->eta),Vec3fa((Vec3fa)material->k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Material //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void Material__preprocess(std::vector<Material *> materials, unsigned int materialID,
|
||||||
|
BRDF &brdf, const Vec3fa &wo, const Sample &sp)
|
||||||
|
{
|
||||||
|
auto id = materialID;
|
||||||
|
{
|
||||||
|
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||||
|
{
|
||||||
|
Material *material = materials[id];
|
||||||
|
|
||||||
|
switch (material->type)
|
||||||
|
{
|
||||||
|
case MATERIAL_OBJ:
|
||||||
|
OBJMaterial__preprocess((OBJMaterial *)material, brdf, wo, sp);
|
||||||
|
break;
|
||||||
|
case MATERIAL_MATTE:
|
||||||
|
MatteMaterial__preprocess((MatteMaterial *)material, brdf, wo, sp);
|
||||||
|
break;
|
||||||
|
case MATERIAL_METAL:
|
||||||
|
MetalMaterial__preprocess((MetalMaterial *)material, brdf, wo, sp);
|
||||||
|
break;
|
||||||
|
case MATERIAL_REFLECTIVE_METAL:
|
||||||
|
ReflectiveMetalMaterial__preprocess((ReflectiveMetalMaterial *)material, brdf, wo, sp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa Material__eval(std::vector<Material *> materials, unsigned int materialID,
|
||||||
|
const BRDF &brdf, const Vec3fa &wo, const Sample &sp, const Vec3fa &wi)
|
||||||
|
{
|
||||||
|
Vec3fa c = Vec3fa(0.0f);
|
||||||
|
auto id = materialID;
|
||||||
|
{
|
||||||
|
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||||
|
{
|
||||||
|
Material *material = materials[id];
|
||||||
|
switch (material->type)
|
||||||
|
{
|
||||||
|
case MATERIAL_OBJ:
|
||||||
|
c = OBJMaterial__eval((OBJMaterial *)material, brdf, wo, sp, wi);
|
||||||
|
break;
|
||||||
|
case MATERIAL_MATTE:
|
||||||
|
c = MatteMaterial__eval((MatteMaterial *)material, brdf, wo, sp, wi);
|
||||||
|
break;
|
||||||
|
case MATERIAL_METAL:
|
||||||
|
c = MetalMaterial__eval((MetalMaterial *)material, brdf, wo, sp, wi);
|
||||||
|
break;
|
||||||
|
case MATERIAL_REFLECTIVE_METAL:
|
||||||
|
c = ReflectiveMetalMaterial__eval((ReflectiveMetalMaterial *)material, brdf, wo, sp, wi);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cout << "No Material found" << std::endl;
|
||||||
|
c = Vec3fa(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec3fa Material__sample(std::vector<Material *> materials, unsigned int materialID,
|
||||||
|
const BRDF &brdf, const Vec3fa &Lw, const Vec3fa &wo, const Sample &sp, Sample3f &wi_o,
|
||||||
|
const Vec2f &s)
|
||||||
|
{
|
||||||
|
Vec3fa c = Vec3fa(0.0f);
|
||||||
|
auto id = materialID;
|
||||||
|
{
|
||||||
|
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||||
|
{
|
||||||
|
Material *material = materials[id];
|
||||||
|
switch (material->type)
|
||||||
|
{
|
||||||
|
case MATERIAL_OBJ:
|
||||||
|
c = OBJMaterial__sample((OBJMaterial *)material, brdf, Lw, wo, sp, wi_o, s);
|
||||||
|
break;
|
||||||
|
case MATERIAL_MATTE:
|
||||||
|
c = MatteMaterial__sample((MatteMaterial *)material, brdf, Lw, wo, sp, wi_o, s);
|
||||||
|
break;
|
||||||
|
case MATERIAL_METAL:
|
||||||
|
c = MetalMaterial__sample((MetalMaterial *)material, brdf, Lw, wo, sp, wi_o, s);
|
||||||
|
break;
|
||||||
|
case MATERIAL_REFLECTIVE_METAL:
|
||||||
|
c = ReflectiveMetalMaterial__sample((ReflectiveMetalMaterial *)material, brdf, Lw, wo, sp, wi_o, s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wi_o = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||||
|
c = Vec3fa(0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
0
Framework/external/imgui/backends/vulkan/generate_spv.sh
vendored
Executable file → Normal file
0
Framework/external/imgui/backends/vulkan/generate_spv.sh
vendored
Executable file → Normal 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;
|
||||||
|
|
|
||||||
118
Framework/include/distribution.hpp
Normal file
118
Framework/include/distribution.hpp
Normal 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
185
Framework/include/film.hpp
Normal 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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
37
Framework/include/random_sampler_wrapper.hpp
Normal file
37
Framework/include/random_sampler_wrapper.hpp
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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
38
Framework/scenes/box2.obj
Normal 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
|
||||||
29
Framework/scenes/caustics/ring.mtl
Normal file
29
Framework/scenes/caustics/ring.mtl
Normal 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
|
||||||
1524
Framework/scenes/caustics/ring.obj
Normal file
1524
Framework/scenes/caustics/ring.obj
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue