From 57ae058d9a42bd6acdb1cb0eef43e11fe2c3dbd4 Mon Sep 17 00:00:00 2001 From: hal8174 Date: Tue, 23 Apr 2024 10:33:00 +0200 Subject: [PATCH] Assignment1 --- .gitignore | 1 + Assignments/Assignment1/Application1.cpp | 121 ++++++++ Assignments/Assignment1/Application1.h | 24 ++ Assignments/Assignment1/CMakeLists.txt | 5 +- Assignments/Assignment1/assignment1.cpp | 6 +- Assignments/Assignment1/helper.hpp | 288 ++++++++++++++++++ .../embree/include/embree4/rtcore_config.h | 2 +- 7 files changed, 444 insertions(+), 3 deletions(-) create mode 100644 Assignments/Assignment1/Application1.cpp create mode 100644 Assignments/Assignment1/Application1.h create mode 100644 Assignments/Assignment1/helper.hpp diff --git a/.gitignore b/.gitignore index 378eac2..9785597 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +.cache diff --git a/Assignments/Assignment1/Application1.cpp b/Assignments/Assignment1/Application1.cpp new file mode 100644 index 0000000..29b4aba --- /dev/null +++ b/Assignments/Assignment1/Application1.cpp @@ -0,0 +1,121 @@ +#include "Application1.h" + +void Application1::initScene() { + Data_Constructor(&data, 1, 8); + + /* select scene here */ + standardScene(); + // standardScenewithAreaLight(); +} + +void Application1::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 = loadOBJ(file, false).cast(); + sceneGraph->add(new SceneGraph::LightNodeImpl( + SceneGraph::PointLight(Vec3fa(213, 300, 227), Vec3fa(100000, 100000, 100000)))); + + Ref 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 Application1::standardScenewithAreaLight() { + 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 = loadOBJ(file, false).cast(); + sceneGraph->add(new SceneGraph::LightNodeImpl( + SceneGraph::QuadLight(Vec3fa(343.0, 548.0, 227.0), Vec3fa(343.0, 548.0, 332.0), Vec3fa(213.0, 548.0, 332.0), + Vec3fa(213.0, 548.0, 227.0), Vec3fa(100000, 100000, 100000)))); + + Ref 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; +} + +/* task that renders a single screen tile */ +Vec3fa Application1::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& 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; + int matId = data.scene->geometries[ray.geomID]->materialID; + 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, RandomSampler_get2D(sampler)); + + const Light* l = data.scene->lights[0]; + Light_SampleRes ls = Lights_sample(l, sample, RandomSampler_get2D(sampler)); + Vec3f lightColor = {colorLight[0], colorLight[1], colorLight[2]}; + + Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir); + L += diffuse; + + /* initialize shadow ray */ + Ray shadow(sample.P, ls.dir, 0.001f, ls.dist, 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 += ls.weight * lightColor * 0.1f; + } + } + + return L; +} diff --git a/Assignments/Assignment1/Application1.h b/Assignments/Assignment1/Application1.h new file mode 100644 index 0000000..879b590 --- /dev/null +++ b/Assignments/Assignment1/Application1.h @@ -0,0 +1,24 @@ +#pragma once +#include "helper.hpp" + + +class Application1 : public Application { +public: + Application1(int argc, char** argv) : Application(argc, argv, "Assignment 1") { + } + +private: + Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) override; + + void drawGUI() override { + ImGui::ColorEdit3("Color", colorLight); + } + + void initScene() override; + + void standardScene(); + + void standardScenewithAreaLight(); + + float colorLight[3] = {1.0f, 1.0f, 1.0f}; +}; diff --git a/Assignments/Assignment1/CMakeLists.txt b/Assignments/Assignment1/CMakeLists.txt index 133e26b..0b21510 100644 --- a/Assignments/Assignment1/CMakeLists.txt +++ b/Assignments/Assignment1/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR) project(Assignment1) -add_executable(${PROJECT_NAME} "assignment1.cpp") +add_executable(${PROJECT_NAME} "assignment1.cpp" + Application1.cpp + Application1.h + helper.hpp) target_link_libraries(${PROJECT_NAME} PUBLIC CGI-framework) diff --git a/Assignments/Assignment1/assignment1.cpp b/Assignments/Assignment1/assignment1.cpp index 8cfdb95..e363967 100644 --- a/Assignments/Assignment1/assignment1.cpp +++ b/Assignments/Assignment1/assignment1.cpp @@ -1,5 +1,9 @@ +#include "Application1.h" int main(int argc, char** argv) { - + auto app = new Application1(argc, argv); + + app->run(); + return 0; } diff --git a/Assignments/Assignment1/helper.hpp b/Assignments/Assignment1/helper.hpp new file mode 100644 index 0000000..c534cd9 --- /dev/null +++ b/Assignments/Assignment1/helper.hpp @@ -0,0 +1,288 @@ +#pragma once +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Material // +//////////////////////////////////////////////////////////////////////////////// + +inline void Material__preprocess(std::vector 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; + default: break; + } + } + } +} + +inline Vec3fa Material__eval(std::vector 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; + default: + std::cout << "No Material found" << std::endl; + c = Vec3fa(0.0f); + } + } + } + return c; +} + +inline Vec3fa Material__sample(std::vector 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; + default: wi_o = make_Sample3f(Vec3fa(0.0f), 0.0f); + c = Vec3fa(0.0f); + break; + } + } + } + return c; +} diff --git a/Framework/external/embree/include/embree4/rtcore_config.h b/Framework/external/embree/include/embree4/rtcore_config.h index d4376a8..7a10463 100644 --- a/Framework/external/embree/include/embree4/rtcore_config.h +++ b/Framework/external/embree/include/embree4/rtcore_config.h @@ -26,7 +26,7 @@ #define RTC_MIN_WIDTH EMBREE_MIN_WIDTH #if !defined(EMBREE_STATIC_LIB) -/* #undef EMBREE_STATIC_LIB */ +#define EMBREE_STATIC_LIB #endif /* #undef EMBREE_API_NAMESPACE */