Add path tracer implementation to application3
This commit is contained in:
parent
3369dc0567
commit
fe92493afd
2 changed files with 171 additions and 50 deletions
|
|
@ -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 *> 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);
|
||||
|
||||
const Vec3fa wo = neg(ray.dir);
|
||||
|
||||
/* shade pixels */
|
||||
if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
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 *> 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 *> 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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue