diff --git a/Assignments/Assignment2/Application2.cpp b/Assignments/Assignment2/Application2.cpp index 9221a36..bfa5529 100644 --- a/Assignments/Assignment2/Application2.cpp +++ b/Assignments/Assignment2/Application2.cpp @@ -1,9 +1,11 @@ #include "Application2.h" +#include "embree4/rtcore_common.h" #include "helper.hpp" #include "random_sampler.hpp" +#include "ray.hpp" #include -#define EPS 0.01f +#define EPS 0.0001f void Application2::initScene() { Data_Constructor(&data, 1, 8); @@ -114,6 +116,19 @@ Vec3fa ACESFilm(Vec3fa x, float exposure) { return (x * (a * x + b)) / (x * (c * x + d) + e); } +Sample createSample(Ray &ray) { + Sample sample; + Vec3fa Ns = normalize(ray.Ng); + sample.P = ray.org + ray.tfar * ray.dir; + sample.Ng = ray.Ng; + sample.Ns = Ns; + + sample.Ng = face_forward(ray.dir, normalize(sample.Ng)); + sample.Ns = face_forward(ray.dir, normalize(sample.Ns)); + + return sample; +} + // Function that selects implementation at runtime Vec3fa Application2::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) { if (selected == 0) { @@ -130,6 +145,8 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera& Vec3fa L = Vec3fa(0.0f); Vec3fa Lw = Vec3fa(1.0f); + bool in_volume = scene == 0; + /* 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); @@ -146,6 +163,9 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera& const Vec3fa wo = neg(ray.dir); float mu_t = mu_a + mu_s; + if (!in_volume) { + mu_t = 0; + } float t; if (mu_t == 0) { t = inf; @@ -179,18 +199,70 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera& Ray shadow(sample.P, ls.dir, EPS, ls.dist - EPS, 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); + /* shadow magic */ + + float Lwscatter = 1; + float shadow_near = EPS; + + bool shadow_in_volume = in_volume; + + while (1) { + + /* initialize shadow ray */ + Ray shadow(sample.P, ls.dir, shadow_near, ls.dist - EPS, 0.0f); + + Sample shadowSample = createSample(shadow); + + /* shadow ray */ + RTCIntersectArguments iargs; + rtcInitIntersectArguments(&iargs); + iargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE; + rtcIntersect1(data.g_scene, RTCRayHit_(shadow), &iargs); + RayStats_addRay(stats); + + if (shadow.geomID == RTC_INVALID_GEOMETRY_ID) { + if (shadow_in_volume) { + Lwscatter *= std::pow(M_E, - mu_t * (shadow.tfar - shadow.tnear())); + } + break; + } + + /* calculate BRDF */ + BRDF brdf; + std::vector material_array = data.scene->materials; + + Material__preprocess(material_array, shadow.geomID, brdf, neg(shadow.dir), shadowSample); + + + if (brdf.name == "default") { + + if (shadow_in_volume) { + Lwscatter *= std::pow(M_E, - mu_t * (shadow.tfar - shadow.tnear())); + } + + shadow_in_volume = dot(normalize(shadow.Ng), shadow.dir) < 0; + + shadow_near = shadow.tfar + EPS; + + } else { + Lwscatter = 0.0; + break; + } + + + }; + // /* trace shadow ray */ + // RTCOccludedArguments sargs; + // rtcInitOccludedArguments(&sargs); + // sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE; + // rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs); + // RayStats_addShadowRay(stats); float scatter = phase(scattering_parameter, -dot(-ray.dir,shadow.dir)); /* add light contribution if not occluded (NEE) */ - if (shadow.tfar >= 0.0f) { + if (Lwscatter > 0.0) { // L += Lw * light_diffuse * ls.weight; - L += Lw * std::pow(M_E, - mu_t * shadow.tfar) * scatter * (mu_s / mu_t) * ls.weight * dot(sample.Ng, ls.dir) / data.scene->lights.size(); + L += Lw * Lwscatter * scatter * (mu_s / mu_t) * ls.weight * dot(sample.Ng, ls.dir) / data.scene->lights.size(); // L += Lw * light_diffuse * ls.weight/ data.scene->lights.size(); } @@ -204,16 +276,11 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera& ray = Ray(ray.org + t * ray.dir,o,EPS,inf); } else 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; + + + Sample sample = createSample(ray); int matId = data.scene->geometries.at(ray.geomID)->materialID; unsigned lightID = data.scene->geometries.at(ray.geomID)->lightID; - sample.Ng = face_forward(ray.dir, normalize(sample.Ng)); - sample.Ns = face_forward(ray.dir, normalize(sample.Ns)); // include direct light on first ray if (lightID != unsigned(-1)) { @@ -225,52 +292,113 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera& } break; } - + /* calculate BRDF */ BRDF brdf; std::vector material_array = data.scene->materials; Material__preprocess(material_array, matId, brdf, wo, sample); + + if (brdf.name == "default") { - /* Light ray */ - int id = (int)(RandomSampler_get1D(sampler) * data.scene->lights.size()); - if (id == data.scene->lights.size()) - id = data.scene->lights.size() - 1; - // printf("id: %d\n", id); - const Light* l = data.scene->lights.at(id); + in_volume = dot(normalize(ray.Ng), ray.dir) < 0; - Light_SampleRes ls = Lights_sample(l, sample, RandomSampler_get2D(sampler)); + ray = Ray(ray.org + ray.tfar * ray.dir, ray.dir, EPS, inf); - Vec3fa light_diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir); + i--; - /* initialize shadow ray */ - Ray shadow(sample.P, ls.dir, EPS, ls.dist - EPS, 0.0f); + } else { - /* trace shadow ray */ - RTCOccludedArguments sargs; - rtcInitOccludedArguments(&sargs); - sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE; - rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs); - RayStats_addShadowRay(stats); + /* Light ray */ + int id = (int)(RandomSampler_get1D(sampler) * data.scene->lights.size()); + if (id == data.scene->lights.size()) + id = data.scene->lights.size() - 1; + // printf("id: %d\n", id); + const Light* l = data.scene->lights.at(id); - /* add light contribution if not occluded (NEE) */ - if (shadow.tfar >= 0.0f) { - // L += Lw * light_diffuse * ls.weight; - L += Lw * std::pow(M_E, - mu_t * shadow.tfar) *light_diffuse * ls.weight * dot(sample.Ng, ls.dir) / data.scene->lights.size(); - // L += Lw * light_diffuse * ls.weight/ data.scene->lights.size(); - } + Light_SampleRes ls = Lights_sample(l, sample, RandomSampler_get2D(sampler)); + + Vec3fa light_diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir); + + + /* shadow magic */ + + float Lwscatter = 1; + float shadow_near = EPS; + + bool shadow_in_volume = in_volume; + + while (1) { + + /* initialize shadow ray */ + Ray shadow(sample.P, ls.dir, shadow_near, ls.dist - EPS, 0.0f); + + Sample shadowSample = createSample(shadow); + + /* shadow ray */ + RTCIntersectArguments iargs; + rtcInitIntersectArguments(&iargs); + iargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE; + rtcIntersect1(data.g_scene, RTCRayHit_(shadow), &iargs); + RayStats_addRay(stats); + + if (shadow.geomID == RTC_INVALID_GEOMETRY_ID) { + if (shadow_in_volume) { + Lwscatter *= std::pow(M_E, - mu_t * (shadow.tfar - shadow.tnear())); + } + break; + } + + /* calculate BRDF */ + BRDF brdf; + std::vector material_array = data.scene->materials; + + Material__preprocess(material_array, shadow.geomID, brdf, neg(shadow.dir), shadowSample); + + + if (brdf.name == "default") { + + if (shadow_in_volume) { + Lwscatter *= std::pow(M_E, - mu_t * (shadow.tfar - shadow.tnear())); + } + + shadow_in_volume = dot(normalize(shadow.Ng), shadow.dir) < 0; + + shadow_near = shadow.tfar + EPS; + + } else { + Lwscatter = 0.0; + break; + } + + + }; + // /* 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 (NEE) */ + if (Lwscatter > 0.0) { + // L += Lw * light_diffuse * ls.weight; + L += Lw * Lwscatter *light_diffuse * ls.weight * dot(sample.Ng, ls.dir) / data.scene->lights.size(); + // L += Lw * light_diffuse * ls.weight/ data.scene->lights.size(); + } - // Use cosine sampling - Vec2f uv = RandomSampler_get2D(sampler); - Sample3f wi = cosineSampleHemisphere(uv.x, uv.y, sample.Ng); + // Use cosine sampling + Vec2f uv = RandomSampler_get2D(sampler); + Sample3f wi = cosineSampleHemisphere(uv.x, uv.y, sample.Ng); - Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, wi.v); - // printf("pdf: %f\n", wi.pdf); + Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, wi.v); + // printf("pdf: %f\n", wi.pdf); - Lw *= diffuse / wi.pdf; + Lw *= diffuse / wi.pdf; - ray = Ray(sample.P,wi.v,EPS,inf); + ray = Ray(sample.P,wi.v,EPS,inf); + } } } diff --git a/Assignments/Assignment2/Application2.h b/Assignments/Assignment2/Application2.h index 43fce5d..cc37c10 100644 --- a/Assignments/Assignment2/Application2.h +++ b/Assignments/Assignment2/Application2.h @@ -1,6 +1,7 @@ #pragma once #include "helper.hpp" #include "imgui.h" +#include "math/vec3fa.h" class Application2 : public Application { @@ -15,22 +16,28 @@ private: void drawGUI() override { ImGui::Checkbox("Bounding Box", &boundingBox); - ImGui::InputInt("Ray depth", &ray_depth); + if (ImGui::InputInt("Ray depth", &ray_depth)) + clear(); + if (ray_depth < 1) { ray_depth = 1; } const char* items[] = {"Original", "Homogeneous"}; - ImGui::Combo("Version", &selected, items, 2); + if (ImGui::Combo("Version", &selected, items, 2)) + clear(); - ImGui::SliderFloat("mu_a", &mu_a, 0.0, 1.0); - ImGui::SliderFloat("mu_s", &mu_s, 0.0, 1.0); - ImGui::SliderFloat("scattering parameter", &scattering_parameter, -1.0, 1.0); + if (ImGui::SliderFloat("mu_a", &mu_a, 0.0, 1.0)) + clear(); + + if (ImGui::SliderFloat("mu_s", &mu_s, 0.0, 1.0)) + clear(); + + if (ImGui::SliderFloat("scattering parameter", &scattering_parameter, -1.0, 1.0)) + clear(); const char* scenes[] = {"Gnome", "Horse", "Heterogenous"}; - int oldscene = scene; - ImGui::Combo("Scenes", &scene, scenes, 3); - if (scene != oldscene) { + if (ImGui::Combo("Scenes", &scene, scenes, 3)) { Data_Destructor(&data); Data_Constructor(&data, 1, 8); if (scene == 0) @@ -42,6 +49,13 @@ private: } } + void clear() { + data.accu_count = 0;; + for (size_t i = 0; i < data.accu_width * data.accu_height; i++) { + data.accu[i] = Vec3fx(0.0); + } + } + void initScene() override; void emptyScene();