241 lines
7.9 KiB
C++
241 lines
7.9 KiB
C++
#include "Application3.h"
|
|
#include "math/vec3fa.h"
|
|
|
|
#define EPS 0.001f
|
|
|
|
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) * 10);
|
|
|
|
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) {
|
|
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 *> 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);
|
|
|
|
/* 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));
|
|
|
|
// include direct light on first ray
|
|
if (lightID != unsigned(-1)) {
|
|
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 *> 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;
|
|
}
|