diff --git a/Assignments/Assignment3/Application3.cpp b/Assignments/Assignment3/Application3.cpp index 28f405c..f33231f 100644 --- a/Assignments/Assignment3/Application3.cpp +++ b/Assignments/Assignment3/Application3.cpp @@ -1,5 +1,7 @@ #include "Application3.h" +#include "math/vec3fa.h" +#define EPS 0.01f void Application3::initScene() { Data_Constructor(&data, 1, 8); @@ -46,7 +48,7 @@ void Application3::causticScene() { 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)); + Vec3fa(50, 50, 50) * 10); sceneGraph->add(light); @@ -72,6 +74,80 @@ void Application3::causticScene() { /* task that renders a single screen tile */ Vec3fa Application3::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler) { + if (method == 0) { + return renderPixelPT(x,y , camera, stats, sampler); + } else if (method == 1) { + return renderPixelNEE(x,y , camera, stats, sampler); + } else { + return Vec3fa(0.0); + } +} + +Vec3fa Application3::renderPixelPT(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); + + + for (int i = 0; i < ray_depth; i++) { + /* 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) { + break; + } + + + Vec3fa Ns = normalize(ray.Ng); + Sample sample; + sample.P = ray.org + ray.tfar * ray.dir; + sample.Ng = ray.Ng; + sample.Ns = Ns; + int matId = data.scene->geometries[ray.geomID]->materialID; + unsigned lightID = data.scene->geometries[ray.geomID]->lightID; + sample.Ng = face_forward(ray.dir, normalize(sample.Ng)); + sample.Ns = face_forward(ray.dir, normalize(sample.Ns)); + + // evaluate light + if (lightID != unsigned(-1)) { + const Light* l = data.scene->lights[lightID]; + Light_EvalRes evalRes = Lights_eval(l, sample, -wo); + return Lw * evalRes.value; + break; + } + + /* calculate BRDF */ + BRDF brdf; + std::vector material_array = data.scene->materials; + Material__preprocess(material_array, matId, brdf, wo, sample); + + + Vec2f uv = sampler.get2D(); + Sample3f wi; + Vec3fa diffuse = Material__sample(material_array, matId, brdf, Lw, wo, sample, wi, uv); + + Lw *= diffuse / wi.pdf; + + ray = Ray(sample.P,wi.v,EPS,inf); + + } + + return L; +} + +Vec3fa Application3::renderPixelNEE(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); @@ -80,67 +156,84 @@ Vec3fa Application3::renderPixel(float x, float y, const ISPCCamera& camera, 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); + for (int i = 0; i < ray_depth; i++) { + /* 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); - /* shade pixels */ - if (ray.geomID != RTC_INVALID_GEOMETRY_ID) { + const Vec3fa wo = neg(ray.dir); + + /* shade pixels */ + if (ray.geomID == RTC_INVALID_GEOMETRY_ID) { + break; + } + + 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; + int matId = data.scene->geometries[ray.geomID]->materialID; unsigned lightID = data.scene->geometries[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)) { - 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_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; + if (i == 0) { + const Light* l = data.scene->lights[lightID]; + Light_EvalRes evalRes = Lights_eval(l, sample, -wo); + L += Lw * evalRes.value; } + break; } + + /* calculate BRDF */ + BRDF brdf; + std::vector material_array = data.scene->materials; + Material__preprocess(material_array, matId, brdf, wo, sample); + + /* Light ray */ + 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 light_diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir); + + /* initialize shadow ray */ + 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); + + /* add light contribution if not occluded (NEE) */ + if (shadow.tfar >= 0.0f) { + // L += Lw * light_diffuse * ls.weight; + L += Lw * light_diffuse * ls.weight * dot(sample.Ng, ls.dir) / data.scene->lights.size(); + // L += Lw * light_diffuse * ls.weight/ data.scene->lights.size(); + } + + + Vec2f uv = sampler.get2D(); + Sample3f wi; + Vec3fa diffuse = Material__sample(material_array, matId, brdf, Lw, wo, sample, wi, uv); + + Lw *= diffuse / wi.pdf; + + ray = Ray(sample.P,wi.v,EPS,inf); + } return L; diff --git a/Assignments/Assignment3/Application3.h b/Assignments/Assignment3/Application3.h index 896d62b..8541934 100644 --- a/Assignments/Assignment3/Application3.h +++ b/Assignments/Assignment3/Application3.h @@ -1,6 +1,7 @@ #pragma once #include "helper.hpp" #include "application_integrator.h" +#include "simd/vboolf4_sse2.h" class Application3 : public ApplicationIntegrator { @@ -10,10 +11,34 @@ public: private: Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler) override; + Vec3fa renderPixelPT(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler); + Vec3fa renderPixelNEE(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSamplerWrapper& sampler); void drawGUI() override { ApplicationIntegrator::drawGUI(); // NEW! + ImGui::InputInt("Ray depth", &ray_depth); + if (ray_depth < 1) { + ray_depth = 1; + } + + const char* methods[] = {"PT", "NEE"}; + if (ImGui::Combo("Methods", &method, methods, 2)) { + resetRender(); + } + + const char* scenes[] = {"Cornell", "Ring"}; + int oldscene = scene; + ImGui::Combo("Scenes", &scene, scenes, 2); + if (scene != oldscene) { + Data_Destructor(&data); + Data_Constructor(&data, 1, 8); + if (scene == 0) + standardScene(); + if (scene == 1) + causticScene(); + } + } void initScene() override; @@ -23,4 +48,7 @@ private: void causticScene(); float colorLight[3] = {1.0f, 1.0f, 1.0f}; + int ray_depth = 5; + int scene = 0; + int method = 0; };