Skip to content

Commit

Permalink
Add the direct lighting integrator.
Browse files Browse the repository at this point in the history
  • Loading branch information
tatsy committed Mar 10, 2016
1 parent f639a7b commit d2b15f4
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 75 deletions.
Binary file modified results/mi_1000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions sources/core/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ void Engine::start(const std::string& filename) const {
xml.get<std::string>("scene.integrator.<xmlattr>.type");
if (intgrName == "path") {
integrator.reset(new PathIntegrator(camera, sampler));
} else if (intgrName == "direct") {
integrator.reset(new DirectLightingIntegrator(camera, sampler));
} else if (intgrName == "sppm") {
integrator.reset(new SPPMIntegrator(camera, sampler));
} else {
Expand Down
2 changes: 2 additions & 0 deletions sources/integrator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(SOURCES
# ${CMAKE_CURRENT_LIST_DIR}/renderer_helper.cc
${CMAKE_CURRENT_LIST_DIR}/pathtrace.cc
${CMAKE_CURRENT_LIST_DIR}/volpath.cc
${CMAKE_CURRENT_LIST_DIR}/directlighting.cc
# ${CMAKE_CURRENT_LIST_DIR}/bdpt.cc
# ${CMAKE_CURRENT_LIST_DIR}/mlt.cc
# ${CMAKE_CURRENT_LIST_DIR}/photon_map.cc
Expand All @@ -23,6 +24,7 @@ set(HEADERS
# ${CMAKE_CURRENT_LIST_DIR}/renderer_helper.h
${CMAKE_CURRENT_LIST_DIR}/pathtrace.h
${CMAKE_CURRENT_LIST_DIR}/volpath.h
${CMAKE_CURRENT_LIST_DIR}/directlighting.h
# ${CMAKE_CURRENT_LIST_DIR}/bdpt.h
# ${CMAKE_CURRENT_LIST_DIR}/mlt.h
# ${CMAKE_CURRENT_LIST_DIR}/photon_map.h
Expand Down
56 changes: 56 additions & 0 deletions sources/integrator/directlighting.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#define SPICA_API_EXPORT
#include "directlighting.h"

#include "../core/interaction.h"
#include "../scenes/scene.h"

#include "mis.h"
#include "render_parameters.h"

namespace spica {

DirectLightingIntegrator::DirectLightingIntegrator(
const std::shared_ptr<const Camera>& camera,
const std::shared_ptr<Sampler>& sampler)
: SamplerIntegrator{ camera, sampler } {
}

Spectrum DirectLightingIntegrator::Li(const Scene& scene,
const RenderParameters& params,
const Ray& r,
Sampler& sampler,
MemoryArena& arena,
int depth) const {
Ray ray(r);
Spectrum L(0.0);
SurfaceInteraction isect;
if (!scene.intersect(ray, &isect)) {
for (const auto& light : scene.lights()) {
L += light->Le(ray);
}
return L;
}

isect.setScatterFuncs(ray, arena);
if (!isect.bsdf()) {
Ray nextRay = isect.spawnRay(ray.dir());
return Li(scene, params, nextRay, sampler, arena, depth);
}

if (depth == 0) {
L += isect.Le(-ray.dir());
}

Vector3d wo = isect.wo();
if (scene.lights().size() > 0) {
L += mis::uniformSampleOneLight(isect, scene, arena, sampler);
}

if (depth + 1 < params.bounceLimit()) {
L += specularReflect(scene, params, ray, isect, sampler, arena, depth + 1);
L += specularTransmit(scene, params, ray, isect, sampler, arena, depth + 1);
}
return L;
}

} // namespace spica
28 changes: 28 additions & 0 deletions sources/integrator/directlighting.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifdef _MSC_VER
#pragma once
#endif

#ifndef _SPICA_DIRECTLIGHTING_H_
#define _SPICA_DIRECTLIGHTING_H_

#include "integrator.h"

namespace spica {

class SPICA_EXPORTS DirectLightingIntegrator : public SamplerIntegrator {
public:
// Public methods
DirectLightingIntegrator(const std::shared_ptr<const Camera>& camera,
const std::shared_ptr<Sampler>& sampler);

Spectrum Li(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
Sampler& sampler,
MemoryArena& arena,
int depth = 0) const override;
};

} // namespace spica

#endif // _SPICA_DIRECTLIGHTING_H_
128 changes: 127 additions & 1 deletion sources/integrator/integrator.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,139 @@
#define SPICA_API_EXPORT
#include "integrator.h"

#include "../core/memory.h"
#include "../core/interaction.h"

#include "../bxdf/bxdf.h"
#include "../bxdf/bsdf.h"

#include "../camera/camera.h"
#include "../image/film.h"
#include "../random/sampler.h"
#include "render_parameters.h"

namespace spica {

Integrator::Integrator(std::shared_ptr<Camera>& camera)
// -----------------------------------------------------------------------------
// Integrator method definitions
// -----------------------------------------------------------------------------

Integrator::Integrator(const std::shared_ptr<const Camera>& camera)
: camera_{ camera } {
}

Integrator::~Integrator() {
}

// -----------------------------------------------------------------------------
// SamplerIntegrator method definitions
// -----------------------------------------------------------------------------

SamplerIntegrator::SamplerIntegrator(const std::shared_ptr<const Camera>& camera,
const std::shared_ptr<Sampler>& sampler)
: Integrator{ camera }
, sampler_{ sampler } {
}

SamplerIntegrator::~SamplerIntegrator() {
}

void SamplerIntegrator::render(const Scene& scene,
const RenderParameters& params) const {
// Preparation for accouting for BSSRDF
// _integrator->initialize(scene);

const int width = camera_->film()->resolution().x();
const int height = camera_->film()->resolution().y();

// Prepare samplers and memory arenas
auto samplers = std::vector<std::unique_ptr<Sampler>>(kNumThreads);
auto arenas = std::vector<MemoryArena>(kNumThreads);

// Distribute rendering tasks
const int taskPerThread = (height + kNumThreads - 1) / kNumThreads;
std::vector<std::vector<int> > tasks(kNumThreads);
for (int y = 0; y < height; y++) {
tasks[y % kNumThreads].push_back(y);
}

// Trace rays
for (int i = 0; i < params.samplePerPixel(); i++) {
if (i % kNumThreads == 0) {
// _integrator->construct(scene, params);
}

if (i % 16 == 0) {
for (int t = 0; t < kNumThreads; t++) {
auto seed = static_cast<unsigned int>(time(0) + kNumThreads * i + t);
samplers[t] = sampler_->clone(seed);
}
}

for (int t = 0; t < taskPerThread; t++) {
ompfor (int threadID = 0; threadID < kNumThreads; threadID++) {
samplers[threadID]->startNextSample();
if (t < tasks[threadID].size()) {
const int y = tasks[threadID][t];
for (int x = 0; x < width; x++) {
const Point2d randFilm = samplers[threadID]->get2D();
const Point2d randLens = samplers[threadID]->get2D();
const Ray ray = camera_->spawnRay(Point2i(x, y), randFilm, randLens);

const Point2i pixel(width - x - 1, y);
camera_->film()->
addPixel(pixel, randFilm,
Li(scene, params, ray, *samplers[threadID], arenas[threadID]));
}
}
arenas[threadID].reset();
}
}
camera_->film()->save(i + 1);
}
std::cout << "Finish!!" << std::endl;
}

Spectrum SamplerIntegrator::specularReflect(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
const SurfaceInteraction& isect,
Sampler& sampler,
MemoryArena& arena,
int depth) const {
Vector3d wi, wo = isect.wo();
double pdf;
BxDFType type = BxDFType::Reflection | BxDFType::Specular;
Spectrum f = isect.bsdf()->sample(wo, &wi, sampler.get2D(), &pdf, type);

const Normal3d nrm = isect.normal();
if (pdf > 0.0 && !f.isBlack() && vect::absDot(wi, nrm) != 0.0) {
Ray r = isect.spawnRay(wi);
return f * Li(scene, params, r, sampler, arena, depth + 1) *
vect::absDot(wi, nrm) / pdf;
}
return Spectrum(0.0);
}

Spectrum SamplerIntegrator::specularTransmit(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
const SurfaceInteraction& isect,
Sampler& sampler,
MemoryArena& arena,
int depth) const {
Vector3d wi, wo = isect.wo();
double pdf;
const Point3d& pos = isect.pos();
const Normal3d& nrm = isect.normal();
BxDFType type = BxDFType::Transmission | BxDFType::Specular;
Spectrum f = isect.bsdf()->sample(wo, &wi, sampler.get2D(), &pdf, type);
if (pdf > 0.0 && !f.isBlack() && vect::absDot(wi, nrm) != 0.0) {
Ray r = isect.spawnRay(wi);
return f * Li(scene, params, r, sampler, arena, depth + 1) *
vect::absDot(wi, nrm) / pdf;
}
return Spectrum(0.0);
}

} // namespace spica
50 changes: 47 additions & 3 deletions sources/integrator/integrator.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,58 @@ namespace spica {
class SPICA_EXPORTS Integrator : public Uncopyable {
public:
// Public methods
explicit Integrator(std::shared_ptr<Camera>& camera);
explicit Integrator(const std::shared_ptr<const Camera>& camera);
virtual ~Integrator();
virtual void render(const Scene& scene,
const RenderParameters& params) const = 0;

protected:
std::shared_ptr<Camera>& camera_;
};
std::shared_ptr<const Camera> camera_;

}; // class Integrator

/**
* The sampler integrator interface.
* @details
* This interface class is for integrating with sampling.
*/
class SPICA_EXPORTS SamplerIntegrator : public Integrator {
public:
// Public methods
SamplerIntegrator(const std::shared_ptr<const Camera>& camera,
const std::shared_ptr<Sampler>& sampler);
virtual ~SamplerIntegrator();
virtual void render(const Scene& scene,
const RenderParameters& params) const;

virtual Spectrum Li(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
Sampler& sampler,
MemoryArena& arena,
int depth = 0) const = 0;

Spectrum specularReflect(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
const SurfaceInteraction& isect,
Sampler& sampler,
MemoryArena& arena,
int depth = 0) const;

Spectrum specularTransmit(const Scene& scene,
const RenderParameters& params,
const Ray& ray,
const SurfaceInteraction& isect,
Sampler& sampler,
MemoryArena& arena,
int depth = 0) const;

private:
// Private fields
std::shared_ptr<Sampler> sampler_;

}; // class SamplerIntegrator

} // namespace spica

Expand Down
62 changes: 3 additions & 59 deletions sources/integrator/pathtrace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,71 +33,15 @@

namespace spica {

PathIntegrator::PathIntegrator(std::shared_ptr<Camera>& camera,
std::shared_ptr<Sampler>& sampler)
: Integrator{ camera }
PathIntegrator::PathIntegrator(const std::shared_ptr<Camera>& camera,
const std::shared_ptr<Sampler>& sampler)
: SamplerIntegrator{ camera, sampler }
, sampler_{ sampler } {
}

PathIntegrator::~PathIntegrator() {
}

void PathIntegrator::render(const Scene& scene,
const RenderParameters& params) const {
// Preparation for accouting for BSSRDF
// _integrator->initialize(scene);

const int width = camera_->film()->resolution().x();
const int height = camera_->film()->resolution().y();

// Prepare samplers and memory arenas
auto samplers = std::vector<std::unique_ptr<Sampler>>(kNumThreads);
auto arenas = std::vector<MemoryArena>(kNumThreads);

// Distribute rendering tasks
const int taskPerThread = (height + kNumThreads - 1) / kNumThreads;
std::vector<std::vector<int> > tasks(kNumThreads);
for (int y = 0; y < height; y++) {
tasks[y % kNumThreads].push_back(y);
}

// Trace rays
for (int i = 0; i < params.samplePerPixel(); i++) {
if (i % kNumThreads == 0) {
// _integrator->construct(scene, params);
}

if (i % 16 == 0) {
for (int t = 0; t < kNumThreads; t++) {
auto seed = static_cast<unsigned int>(time(0) + kNumThreads * i + t);
samplers[t] = sampler_->clone(seed);
}
}

for (int t = 0; t < taskPerThread; t++) {
ompfor (int threadID = 0; threadID < kNumThreads; threadID++) {
samplers[threadID]->startNextSample();
if (t < tasks[threadID].size()) {
const int y = tasks[threadID][t];
for (int x = 0; x < width; x++) {
const Point2d randFilm = samplers[threadID]->get2D();
const Point2d randLens = samplers[threadID]->get2D();
const Ray ray = camera_->spawnRay(Point2i(x, y), randFilm, randLens);

const Point2i pixel(width - x - 1, y);
camera_->film()->
addPixel(pixel, randFilm,
Li(scene, params, ray, *samplers[threadID], arenas[threadID]));
}
}
arenas[threadID].reset();
}
}
camera_->film()->save(i);
}
std::cout << "Finish!!" << std::endl;
}

Spectrum PathIntegrator::Li(const Scene& scene,
const RenderParameters& params,
const Ray& r,
Expand Down
Loading

0 comments on commit d2b15f4

Please sign in to comment.