Add state tracking for volumetric rendering.
This commit is contained in:
parent
c1e15155ad
commit
f702e82b4f
2 changed files with 197 additions and 55 deletions
|
|
@ -1,9 +1,11 @@
|
||||||
#include "Application2.h"
|
#include "Application2.h"
|
||||||
|
#include "embree4/rtcore_common.h"
|
||||||
#include "helper.hpp"
|
#include "helper.hpp"
|
||||||
#include "random_sampler.hpp"
|
#include "random_sampler.hpp"
|
||||||
|
#include "ray.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#define EPS 0.01f
|
#define EPS 0.0001f
|
||||||
|
|
||||||
void Application2::initScene() {
|
void Application2::initScene() {
|
||||||
Data_Constructor(&data, 1, 8);
|
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);
|
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
|
// Function that selects implementation at runtime
|
||||||
Vec3fa Application2::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) {
|
Vec3fa Application2::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) {
|
||||||
if (selected == 0) {
|
if (selected == 0) {
|
||||||
|
|
@ -130,6 +145,8 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera&
|
||||||
Vec3fa L = Vec3fa(0.0f);
|
Vec3fa L = Vec3fa(0.0f);
|
||||||
Vec3fa Lw = Vec3fa(1.0f);
|
Vec3fa Lw = Vec3fa(1.0f);
|
||||||
|
|
||||||
|
bool in_volume = scene == 0;
|
||||||
|
|
||||||
/* initialize ray */
|
/* 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,
|
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);
|
inf);
|
||||||
|
|
@ -146,6 +163,9 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera&
|
||||||
const Vec3fa wo = neg(ray.dir);
|
const Vec3fa wo = neg(ray.dir);
|
||||||
|
|
||||||
float mu_t = mu_a + mu_s;
|
float mu_t = mu_a + mu_s;
|
||||||
|
if (!in_volume) {
|
||||||
|
mu_t = 0;
|
||||||
|
}
|
||||||
float t;
|
float t;
|
||||||
if (mu_t == 0) {
|
if (mu_t == 0) {
|
||||||
t = inf;
|
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);
|
Ray shadow(sample.P, ls.dir, EPS, ls.dist - EPS, 0.0f);
|
||||||
|
|
||||||
|
|
||||||
/* trace shadow ray */
|
/* shadow magic */
|
||||||
RTCOccludedArguments sargs;
|
|
||||||
rtcInitOccludedArguments(&sargs);
|
float Lwscatter = 1;
|
||||||
sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
float shadow_near = EPS;
|
||||||
rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs);
|
|
||||||
RayStats_addShadowRay(stats);
|
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 *> 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));
|
float scatter = phase(scattering_parameter, -dot(-ray.dir,shadow.dir));
|
||||||
/* add light contribution if not occluded (NEE) */
|
/* add light contribution if not occluded (NEE) */
|
||||||
if (shadow.tfar >= 0.0f) {
|
if (Lwscatter > 0.0) {
|
||||||
// L += Lw * light_diffuse * ls.weight;
|
// 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();
|
// 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);
|
ray = Ray(ray.org + t * ray.dir,o,EPS,inf);
|
||||||
|
|
||||||
} else if (ray.geomID != RTC_INVALID_GEOMETRY_ID) {
|
} else if (ray.geomID != RTC_INVALID_GEOMETRY_ID) {
|
||||||
|
|
||||||
Vec3fa Ns = normalize(ray.Ng);
|
|
||||||
Sample sample;
|
Sample sample = createSample(ray);
|
||||||
sample.P = ray.org + ray.tfar * ray.dir;
|
|
||||||
sample.Ng = ray.Ng;
|
|
||||||
sample.Ns = Ns;
|
|
||||||
int matId = data.scene->geometries.at(ray.geomID)->materialID;
|
int matId = data.scene->geometries.at(ray.geomID)->materialID;
|
||||||
unsigned lightID = data.scene->geometries.at(ray.geomID)->lightID;
|
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
|
// include direct light on first ray
|
||||||
if (lightID != unsigned(-1)) {
|
if (lightID != unsigned(-1)) {
|
||||||
|
|
@ -225,52 +292,113 @@ Vec3fa Application2::renderPixelHomogeneous(float x, float y, const ISPCCamera&
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate BRDF */
|
/* calculate BRDF */
|
||||||
BRDF brdf;
|
BRDF brdf;
|
||||||
std::vector<Material *> material_array = data.scene->materials;
|
std::vector<Material *> material_array = data.scene->materials;
|
||||||
Material__preprocess(material_array, matId, brdf, wo, sample);
|
Material__preprocess(material_array, matId, brdf, wo, sample);
|
||||||
|
|
||||||
|
if (brdf.name == "default") {
|
||||||
|
|
||||||
/* Light ray */
|
in_volume = dot(normalize(ray.Ng), ray.dir) < 0;
|
||||||
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);
|
|
||||||
|
|
||||||
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 */
|
} else {
|
||||||
Ray shadow(sample.P, ls.dir, EPS, ls.dist - EPS, 0.0f);
|
|
||||||
|
|
||||||
/* trace shadow ray */
|
/* Light ray */
|
||||||
RTCOccludedArguments sargs;
|
int id = (int)(RandomSampler_get1D(sampler) * data.scene->lights.size());
|
||||||
rtcInitOccludedArguments(&sargs);
|
if (id == data.scene->lights.size())
|
||||||
sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
id = data.scene->lights.size() - 1;
|
||||||
rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs);
|
// printf("id: %d\n", id);
|
||||||
RayStats_addShadowRay(stats);
|
const Light* l = data.scene->lights.at(id);
|
||||||
|
|
||||||
/* add light contribution if not occluded (NEE) */
|
Light_SampleRes ls = Lights_sample(l, sample, RandomSampler_get2D(sampler));
|
||||||
if (shadow.tfar >= 0.0f) {
|
|
||||||
// L += Lw * light_diffuse * ls.weight;
|
Vec3fa light_diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir);
|
||||||
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();
|
|
||||||
}
|
/* 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 *> 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
|
// Use cosine sampling
|
||||||
Vec2f uv = RandomSampler_get2D(sampler);
|
Vec2f uv = RandomSampler_get2D(sampler);
|
||||||
Sample3f wi = cosineSampleHemisphere(uv.x, uv.y, sample.Ng);
|
Sample3f wi = cosineSampleHemisphere(uv.x, uv.y, sample.Ng);
|
||||||
|
|
||||||
Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, wi.v);
|
Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, wi.v);
|
||||||
// printf("pdf: %f\n", wi.pdf);
|
// 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);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "helper.hpp"
|
#include "helper.hpp"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "math/vec3fa.h"
|
||||||
|
|
||||||
|
|
||||||
class Application2 : public Application {
|
class Application2 : public Application {
|
||||||
|
|
@ -15,22 +16,28 @@ private:
|
||||||
|
|
||||||
void drawGUI() override {
|
void drawGUI() override {
|
||||||
ImGui::Checkbox("Bounding Box", &boundingBox);
|
ImGui::Checkbox("Bounding Box", &boundingBox);
|
||||||
ImGui::InputInt("Ray depth", &ray_depth);
|
if (ImGui::InputInt("Ray depth", &ray_depth))
|
||||||
|
clear();
|
||||||
|
|
||||||
if (ray_depth < 1) {
|
if (ray_depth < 1) {
|
||||||
ray_depth = 1;
|
ray_depth = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* items[] = {"Original", "Homogeneous"};
|
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);
|
if (ImGui::SliderFloat("mu_a", &mu_a, 0.0, 1.0))
|
||||||
ImGui::SliderFloat("mu_s", &mu_s, 0.0, 1.0);
|
clear();
|
||||||
ImGui::SliderFloat("scattering parameter", &scattering_parameter, -1.0, 1.0);
|
|
||||||
|
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"};
|
const char* scenes[] = {"Gnome", "Horse", "Heterogenous"};
|
||||||
int oldscene = scene;
|
if (ImGui::Combo("Scenes", &scene, scenes, 3)) {
|
||||||
ImGui::Combo("Scenes", &scene, scenes, 3);
|
|
||||||
if (scene != oldscene) {
|
|
||||||
Data_Destructor(&data);
|
Data_Destructor(&data);
|
||||||
Data_Constructor(&data, 1, 8);
|
Data_Constructor(&data, 1, 8);
|
||||||
if (scene == 0)
|
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 initScene() override;
|
||||||
|
|
||||||
void emptyScene();
|
void emptyScene();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue