Skip to content
Snippets Groups Projects
Commit 069af583 authored by mfruehauf's avatar mfruehauf :game_die:
Browse files

Add two sided area lights

parent 833f2d64
No related branches found
No related tags found
No related merge requests found
...@@ -114,7 +114,7 @@ public: ...@@ -114,7 +114,7 @@ public:
float phi = M_PI * area * m_radiance.maxCoeff(); float phi = M_PI * area * m_radiance.maxCoeff();
BoundingBox3f bbox = triangle->getBoundingBox(0); BoundingBox3f bbox = triangle->getBoundingBox(0);
Vector3f n = triangle->getNormal(); Vector3f n = triangle->getNormal();
return EmitterBounds(bbox, n, phi, 1, 0); return EmitterBounds(bbox, n, phi, 1, 0, true);
} }
virtual bool isAreaLight() const override { return true; } virtual bool isAreaLight() const override { return true; }
......
...@@ -39,11 +39,11 @@ struct EmitterBounds { ...@@ -39,11 +39,11 @@ struct EmitterBounds {
EmitterBounds() EmitterBounds()
: bounds(BoundingBox3f(Point3f::Zero())), w(Vector3f::Zero()), phi(0), : bounds(BoundingBox3f(Point3f::Zero())), w(Vector3f::Zero()), phi(0),
cosTheta_o(1), cosTheta_e(0){}; cosTheta_o(1), cosTheta_e(0), twoSided(false) {};
EmitterBounds(const BoundingBox3f &bounds, const Vector3f &w, float phi, EmitterBounds(const BoundingBox3f &bounds, const Vector3f &w, float phi,
float cosTheta_o, float cosTheta_e) float cosTheta_o, float cosTheta_e, bool twoSided)
: bounds(bounds), w(w), phi(phi), cosTheta_o(cosTheta_o), : bounds(bounds), w(w), phi(phi), cosTheta_o(cosTheta_o),
cosTheta_e(cosTheta_e){}; cosTheta_e(cosTheta_e), twoSided(twoSided){};
Point3f centroid() const { return bounds.getCenter(); } Point3f centroid() const { return bounds.getCenter(); }
...@@ -66,6 +66,9 @@ struct EmitterBounds { ...@@ -66,6 +66,9 @@ struct EmitterBounds {
Vector3f wi = (p - bound_center).normalized(); Vector3f wi = (p - bound_center).normalized();
float cos_theta = wi.dot(w); float cos_theta = wi.dot(w);
if (twoSided) {
cos_theta = abs(cos_theta);
}
float sin_theta = sqrt(1.f - cos_theta * cos_theta); float sin_theta = sqrt(1.f - cos_theta * cos_theta);
// this is a valid formulation for cos(max(a - b, 0)) for a, b in [0, pi] // this is a valid formulation for cos(max(a - b, 0)) for a, b in [0, pi]
...@@ -126,7 +129,7 @@ struct EmitterBounds { ...@@ -126,7 +129,7 @@ struct EmitterBounds {
"cosTheta_o=%f,\n" "cosTheta_o=%f,\n"
"two_sided=%d ]", "two_sided=%d ]",
bounds.toString(), w.toString(), phi, cosTheta_o, bounds.toString(), w.toString(), phi, cosTheta_o,
cosTheta_e, two_sided); cosTheta_e, twoSided);
} }
BoundingBox3f bounds; BoundingBox3f bounds;
...@@ -136,7 +139,7 @@ struct EmitterBounds { ...@@ -136,7 +139,7 @@ struct EmitterBounds {
float phi = 0; // total power of the light float phi = 0; // total power of the light
float cosTheta_o, cosTheta_e; float cosTheta_o, cosTheta_e;
// nori does not handle two sided light sources at the moment // nori does not handle two sided light sources at the moment
bool two_sided = false; bool twoSided = false;
static EmitterBounds merge(const EmitterBounds &a, const EmitterBounds &b) { static EmitterBounds merge(const EmitterBounds &a, const EmitterBounds &b) {
if (a.phi == 0) { if (a.phi == 0) {
...@@ -154,7 +157,7 @@ struct EmitterBounds { ...@@ -154,7 +157,7 @@ struct EmitterBounds {
ext_bounds.expandBy(b.bounds); ext_bounds.expandBy(b.bounds);
return EmitterBounds(ext_bounds, cone.w, a.phi + b.phi, cos_theta_o, return EmitterBounds(ext_bounds, cone.w, a.phi + b.phi, cos_theta_o,
cos_theta_e); cos_theta_e, a.twoSided | b.twoSided);
} }
}; };
......
...@@ -198,7 +198,7 @@ public: ...@@ -198,7 +198,7 @@ public:
const float phi = const float phi =
(M_PI * m_radius * m_radius * colorLookup(Point2f(.5f, .5f))) (M_PI * m_radius * m_radius * colorLookup(Point2f(.5f, .5f)))
.maxCoeff(); .maxCoeff();
return EmitterBounds(sphere_bounds, Vector3f::UnitZ(), phi, -1, 0); return EmitterBounds(sphere_bounds, Vector3f::UnitZ(), phi, -1, 0, false);
} }
virtual Color3f samplePhoton(Ray3f &ray, const Point2f &sample1, virtual Color3f samplePhoton(Ray3f &ray, const Point2f &sample1,
......
...@@ -34,11 +34,13 @@ public: ...@@ -34,11 +34,13 @@ public:
if (!scene->rayIntersect(ray, its)) { if (!scene->rayIntersect(ray, its)) {
break; break;
} }
ctx = LightSamplingContext(its.p, its.shFrame.n);
if (its.mesh != nullptr && its.mesh->isEmitter()) { if (its.mesh != nullptr && its.mesh->isEmitter()) {
lRec = EmitterQueryRecord(ray.o, its.p, its.shFrame.n); lRec = EmitterQueryRecord(ray.o, its.p, its.shFrame.n);
ctx = LightSamplingContext(its.p, its.shFrame.n);
// the light pdf is the product of the emitter pdf and the pmf of
// sampling that light
mat_light_pdf = its.mesh->getEmitter()->pdf(lRec) * mat_light_pdf = its.mesh->getEmitter()->pdf(lRec) *
m_light_sampler->pmf(ctx, its.mesh->getEmitter()); m_light_sampler->pmf(ctx, its.mesh->getEmitter());
w_mat = bRec.measure != EMeasure::ESolidAngle w_mat = bRec.measure != EMeasure::ESolidAngle
...@@ -71,15 +73,14 @@ public: ...@@ -71,15 +73,14 @@ public:
// do { // do {
// light = m_light_sampler->sample(ctx, sampler->next1D()); // light = m_light_sampler->sample(ctx, sampler->next1D());
// } while (light == nullptr); // } while (light == nullptr);
ctx = LightSamplingContext(its.p, its.shFrame.n);
Emitter* light = m_light_sampler->sample(ctx, sampler->next1D()); Emitter *light = m_light_sampler->sample(ctx, sampler->next1D());
if (!light) break; if (!light)
break;
lRec_light.ref = its.p; lRec_light.ref = its.p;
// light power needs to be scaled by the inverse pdf of choosing that Color3f Le_2 = light->sample(lRec_light, sampler->next2D()) / ctx.pdf;
// light em_light_pdf = ctx.pdf * light->pdf(lRec_light);
Color3f Le_2 = light->sample(lRec_light, sampler->next2D());
em_light_pdf = light->pdf(lRec_light) * ctx.pdf;
if (!scene->rayIntersect(lRec_light.shadowRay, its_nee) || if (!scene->rayIntersect(lRec_light.shadowRay, its_nee) ||
its_nee.mesh->isEnvironmentLight()) { its_nee.mesh->isEnvironmentLight()) {
...@@ -94,8 +95,8 @@ public: ...@@ -94,8 +95,8 @@ public:
w_em = isnan(w_em) ? 0.f : w_em; w_em = isnan(w_em) ? 0.f : w_em;
float cos_theta = std::max(0.f, Frame::cosTheta(bRec_light.wo)); float cos_theta = std::max(0.f, Frame::cosTheta(bRec_light.wo));
Li += Color3f f_a = its.mesh->getBSDF()->eval(bRec_light);
w_em * t * cos_theta * its.mesh->getBSDF()->eval(bRec_light) * Le_2; Li += w_em * t * cos_theta * f_a * Le_2;
} }
t *= f; t *= f;
......
...@@ -35,7 +35,7 @@ public: ...@@ -35,7 +35,7 @@ public:
virtual EmitterBounds bounds() const override { virtual EmitterBounds bounds() const override {
BoundingBox3f bbox{}; BoundingBox3f bbox{};
return EmitterBounds(bbox, Vector3f::UnitZ(), m_power.maxCoeff(), -1, 0); return EmitterBounds(bbox, Vector3f::UnitZ(), m_power.maxCoeff(), -1, 0, false);
} }
std::string toString() const { std::string toString() const {
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<scene> <scene>
<integrator type="path_mis"> <integrator type="path_mis">
<lightsampler type="mls" /> <lightsampler type="mls" />
<!-- <lightsampler type="uniform_light" /> -->
</integrator> </integrator>
<camera type="perspective"> <camera type="perspective">
...@@ -18,7 +17,7 @@ ...@@ -18,7 +17,7 @@
</camera> </camera>
<sampler type="independent"> <sampler type="independent">
<integer name="sampleCount" value="16" /> <integer name="sampleCount" value="32" />
</sampler> </sampler>
<mesh type="obj"> <mesh type="obj">
...@@ -60,10 +59,10 @@ ...@@ -60,10 +59,10 @@
</mesh> </mesh>
<mesh type="obj"> <mesh type="obj">
<string name="filename" value="meshes/100_lights.obj" /> <string name="filename" value="meshes/1000_lights.obj" />
<emitter type="area"> <emitter type="area">
<color name="radiance" value="1 1 1" /> <color name="radiance" value="15 15 15" />
</emitter> </emitter>
</mesh> </mesh>
</scene> </scene>
\ No newline at end of file
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</camera> </camera>
<sampler type="independent"> <sampler type="independent">
<integer name="sampleCount" value="16" /> <integer name="sampleCount" value="32" />
</sampler> </sampler>
<mesh type="obj"> <mesh type="obj">
...@@ -59,10 +59,10 @@ ...@@ -59,10 +59,10 @@
</mesh> </mesh>
<mesh type="obj"> <mesh type="obj">
<string name="filename" value="meshes/100_lights.obj" /> <string name="filename" value="meshes/1000_lights.obj" />
<emitter type="area"> <emitter type="area">
<color name="radiance" value="1 1 1" /> <color name="radiance" value="15 15 15" />
</emitter> </emitter>
</mesh> </mesh>
</scene> </scene>
\ No newline at end of file
This diff is collapsed.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment