Skip to content

Commit

Permalink
Merge pull request #41 from blacklab/karsten-furnace-test#22
Browse files Browse the repository at this point in the history
Furnace test#22
  • Loading branch information
boxdot committed Mar 3, 2016
2 parents 1725d2b + cc8c193 commit a2df681
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 78 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ TESTS = \
test_intersection \
test_lambertian \
test_types \
test_sampling
test_sampling \
test_config

test-all: genfiles/stress_test_kdtree test
$<
Expand Down
5 changes: 5 additions & 0 deletions lib/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ float fmax(float x, float y, float z);
struct Box { Vec min, max; };
Box operator+(const Box& a, const Box& b);

// Light Source
struct Light {
Vec position;
Color color;
};

// Ray with precomputed inverse direction
struct Ray : public aiRay {
Expand Down
70 changes: 39 additions & 31 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ R"(Usage: raytracer <filename> [options]
-m --monte-carlo-samples=<int> Monto Carlo samples per ray [default: 8].
Used only in pathtracer.
-t --threads=<int> Number of threads [default: 1].
--inverse-gamma=<float> Inverse of gamma for gamma correction
[default: 0.454545].
--no-gamma-correction Disables gamma correction.
)";

int main(int argc, char const *argv[])
Expand All @@ -89,14 +92,15 @@ int main(int argc, char const *argv[])
std::map<std::string, docopt::value> args =
docopt::docopt(USAGE, {argv + 1, argv + argc}, true, "raytracer 0.2");

Configuration conf;
conf.max_depth = args["--max-depth"].asLong();
conf.shadow_intensity = std::stof(args["--shadow"].asString());
conf.num_pixel_samples = args["--pixel-samples"].asLong();
conf.num_monte_carlo_samples = args["--monte-carlo-samples"].asLong();
conf.num_threads = args["--threads"].asLong();
conf.parse_bg_color(args["--background"].asString());
conf.check();
const Configuration conf { args["--max-depth"].asLong()
, std::stof(args["--shadow"].asString())
, args["--pixel-samples"].asLong()
, args["--monte-carlo-samples"].asLong()
, args["--threads"].asLong()
, args["--background"].asString()
, std::stof(args["--inverse-gamma"].asString())
, args["--no-gamma-correction"].asBool()
};

// import scene
Assimp::Importer importer;
Expand Down Expand Up @@ -127,18 +131,25 @@ int main(int argc, char const *argv[])
const Camera cam(camNode->mTransformation, sceneCam);

// setup light
assert(scene->mNumLights == 1); // we can deal only with a single light
auto& light = *scene->mLights[0];

auto* lightNode = scene->mRootNode->FindNode(light.mName);
assert(lightNode != nullptr);
const auto& LT = lightNode->mTransformation;
auto light_pos = LT * aiVector3D();
auto light_color = aiColor4D{
light.mColorDiffuse.r,
light.mColorDiffuse.g,
light.mColorDiffuse.b,
1};
// we can deal only with one single or no light at all
assert(scene->mNumLights == 0 || scene->mNumLights == 1);
std::vector<Light> lights;
if(scene->mNumLights == 1) {
auto& rawLight = *scene->mLights[0];

auto* lightNode = scene->mRootNode->FindNode(rawLight.mName);
assert(lightNode != nullptr);
const auto& LT = lightNode->mTransformation;
lights.push_back(
{ LT * aiVector3D()
, aiColor4D
{ rawLight.mColorDiffuse.r
, rawLight.mColorDiffuse.g
, rawLight.mColorDiffuse.b
, 1
}
});
}

// load triangles from the scene into a kd-tree
auto triangles = triangles_from_scene(scene);
Expand All @@ -159,17 +170,12 @@ int main(int argc, char const *argv[])

std::cerr << "Rendering ";

// TODO: Use conf.
constexpr float inv_gamma = 1.f/2.2f;

// TODO: Use conf.
ThreadPool pool(4);
ThreadPool pool(conf.num_threads);
std::vector<std::future<void>> tasks;

for (int y = 0; y < height; ++y) {
tasks.emplace_back(pool.enqueue([
&image, &cam, &tree, &light_pos, &light_color,
width, height, y, &conf]()
&image, &cam, &tree, &lights, width, height, y, &conf]()
{
float dx, dy;
xorshift64star<float> gen(42);
Expand All @@ -184,15 +190,17 @@ int main(int argc, char const *argv[])

Stats::instance().num_prim_rays += 1;
image(x, y) += trace(cam.mPosition, cam_dir, tree,
light_pos, light_color, 0, conf);
lights, 0, conf);
}
image(x, y) /=
static_cast<float>(conf.num_pixel_samples);

// gamma correction
image(x, y).r = powf(image(x, y).r, inv_gamma);
image(x, y).g = powf(image(x, y).g, inv_gamma);
image(x, y).b = powf(image(x, y).b, inv_gamma);
if (conf.gamma_correction_enabled) {
image(x, y).r = powf(image(x, y).r, conf.inverse_gamma);
image(x, y).g = powf(image(x, y).g, conf.inverse_gamma);
image(x, y).b = powf(image(x, y).b, conf.inverse_gamma);
}
}
}));
}
Expand Down
46 changes: 23 additions & 23 deletions pathtracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
#include "lib/stats.h"
#include "lib/output.h"

// Color trace(const Vec& origin, const Vec& dir,
// const Tree& triangles, const Vec& light_pos,
// const Color& light_color, int depth, const Configuration& conf)
Color trace(const Vec& origin, const Vec& dir,
const Tree& triangles, const Vec& light_pos,
const Color& light_color, int depth, const Configuration& conf)
const Tree& triangles, const std::vector<Light>& lights,
int depth, const Configuration& conf)
{
if (depth > conf.max_depth) {
return {};
Expand All @@ -25,32 +22,35 @@ Color trace(const Vec& origin, const Vec& dir,
return conf.bg_color;
}

//
// Direct lightning
//

Color direct_lightning;

// light direction
auto p = origin + dist_to_triangle * dir;
auto light_dir = (light_pos - p).Normalize();

// interpolate normal
const auto& triangle = *triangle_pt;
auto normal = triangle.interpolate_normal(1.f - s - t, s, t);

auto p2 = p + normal * 0.0001f;

light_dir = (light_pos - p2).Normalize();
float dist_to_light = (light_pos - p2).Length();
float dist_to_next_triangle;
auto has_shadow = triangles.intersect(
aiRay(p2, light_dir), dist_to_next_triangle, s, t);
//
// Direct lightning
//

// Do we get direct light?
if (!has_shadow || dist_to_next_triangle > dist_to_light) {
// lambertian
direct_lightning = std::max(0.f, light_dir * normal) * light_color;
Color direct_lightning;

for (auto& light : lights) {
// light direction
auto light_dir = (light.position - p).Normalize();

light_dir = (light.position - p2).Normalize();
float dist_to_light = (light.position - p2).Length();
float dist_to_next_triangle;
auto has_shadow = triangles.intersect(
aiRay(p2, light_dir), dist_to_next_triangle, s, t);

// Do we get direct light?
if (!has_shadow || dist_to_next_triangle > dist_to_light) {
// lambertian
direct_lightning = std::max(0.f, light_dir * normal) * light.color;
}
}

//
Expand All @@ -71,7 +71,7 @@ Color trace(const Vec& origin, const Vec& dir,
auto cos_theta = dir_theta.second;

const auto indirect_light = trace(
p2, dir, triangles, light_pos, light_color, depth + 1, conf);
p2, dir, triangles, lights, depth + 1, conf);

// lambertian
indirect_lightning += cos_theta * indirect_light;
Expand Down
16 changes: 9 additions & 7 deletions raytracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
#include "lib/stats.h"

Color trace(const Vec& origin, const Vec& dir,
const Tree& triangles_tree, const Vec& light_pos,
const Color& light_color, int depth, const Configuration& conf)
const Tree& triangles_tree, const std::vector<Light>& lights,
int depth, const Configuration& conf)
{
Stats::instance().num_rays += 1;

if (depth > conf.max_depth) {
return {};
}

auto& light = lights.front();

// intersection
float dist_to_triangle, s, t;
auto triangle_pt = triangles_tree.intersect(
Expand All @@ -22,15 +24,15 @@ Color trace(const Vec& origin, const Vec& dir,

// light direction
auto p = origin + dist_to_triangle * dir;
auto light_dir = (light_pos - p).Normalize();
auto light_dir = (light.position - p).Normalize();

// interpolate normal
const auto& triangle = *triangle_pt;
auto normal = triangle.interpolate_normal(1.f - s - t, s, t);

// direct light
auto direct_lightning = 0.9f * lambertian(
light_dir, normal, triangle.diffuse, light_color);
light_dir, normal, triangle.diffuse, light.color);

// move slightly in direction of normal
auto p2 = p + normal * 0.0001f;
Expand All @@ -40,14 +42,14 @@ Color trace(const Vec& origin, const Vec& dir,
auto reflected_ray_dir = dir - 2.f * (normal * dir) * normal;
auto reflected_color = triangle.diffuse * 0.1f * trace(
p2, reflected_ray_dir,
triangles_tree, light_pos, light_color, depth + 1, conf);
triangles_tree, lights, depth + 1, conf);

auto result = direct_lightning + reflected_color;

// shadow
float dist_to_next_triangle;
light_dir = (light_pos - p2).Normalize();
float dist_to_light = (light_pos - p2).Length();
light_dir = (light.position - p2).Normalize();
float dist_to_light = (light.position - p2).Length();

auto has_shadow = triangles_tree.intersect(
aiRay(p2, light_dir), dist_to_next_triangle, s, t);
Expand Down
Binary file added scenes/furnace_test.blend
Binary file not shown.
Binary file added scenes/furnace_test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions test_assimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ int main(int argc, char const *argv[])

aiColor4D color;
material->Get(AI_MATKEY_COLOR_DIFFUSE, color);
std::cout << color << std::endl;
std::cout << "Diffuse " << color << std::endl;
material->Get(AI_MATKEY_COLOR_AMBIENT, color);
std::cout << color << std::endl;
std::cout << "Ambient " << color << std::endl;
material->Get(AI_MATKEY_COLOR_SPECULAR, color);
std::cout << color << std::endl;
std::cout << "Specular " << color << std::endl;
material->Get(AI_MATKEY_COLOR_EMISSIVE, color);
std::cout << color << std::endl;
std::cout << "Emissive " << color << std::endl;
material->Get(AI_MATKEY_COLOR_TRANSPARENT, color);
std::cout << color << std::endl;
material->Get(AI_MATKEY_COLOR_REFLECTIVE, color);
Expand Down
50 changes: 50 additions & 0 deletions tests/test_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <catch.hpp>
#include "../trace.h"

SCENARIO("Create config from options", "[config]") {

GIVEN("A a max depth") {
long max_depth = 2;

GIVEN("A shadow intensity") {
float shadow_intensity = 1.0f;

GIVEN("A number of pixel samples") {
long num_pixel_samples = 128;

GIVEN("A number of monte carlo samples") {
long num_monte_carlo_samples = 2;

GIVEN("A number of threads") {
long num_threads = 4;

GIVEN("A background color") {
std::string bg_color = "0 0.3 1.0";

GIVEN("An inverse of gamma") {
float inv_gamma = 1.f/2.2f;

GIVEN("A gamma correction flag") {
bool no_gamma = false;

WHEN("the configuration is created") {
Configuration config { max_depth
, shadow_intensity
, num_pixel_samples
, num_monte_carlo_samples
, num_threads
, bg_color
, inv_gamma
, no_gamma
};

THEN("the configuration holds all variables") {
REQUIRE(config.max_depth == 2);
REQUIRE(config.shadow_intensity - 1.0f < 0.00001f);
REQUIRE(config.num_pixel_samples == 128);
REQUIRE(config.num_monte_carlo_samples == 2);
REQUIRE(config.num_threads == 4);
REQUIRE(config.gamma_correction_enabled == true);
REQUIRE(config.bg_color == Color(0.0f, 0.3f, 1.0f, 1.0f));
}}}}}}}}}}
}
2 changes: 1 addition & 1 deletion tests/test_lambertian.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "catch.hpp"
#include <catch.hpp>
#include "../lib/lambertian.h"

#include <assimp/mesh.h>
Expand Down
Loading

0 comments on commit a2df681

Please sign in to comment.