Started sketching the photon mapping.

This commit is contained in:
2017-02-21 17:00:49 -04:00
parent 4e9a30d0b5
commit 2efb8b33d4
5 changed files with 226 additions and 5 deletions

View File

@@ -3,7 +3,7 @@ TARGET = ray
OBJECTS = main.o sampling.o camera.o environment.o disk.o plane.o sphere.o \
phong_brdf.o hsa_brdf.o directional_light.o point_light.o \
spot_light.o sphere_area_light.o disk_area_light.o scene.o tracer.o \
path_tracer.o whitted_tracer.o rgbe.o kd_tree.o
path_tracer.o whitted_tracer.o rgbe.o kd_tree.o photon_tracer.o
DEPENDS = $(OBJECTS:.o=.d)
CXXFLAGS = -ansi -pedantic -Wall -DGLM_FORCE_RADIANS -fopenmp
LDLIBS = -lfreeimage -ljson_spirit

View File

@@ -17,9 +17,7 @@ struct Vec3
float y;
float z;
Vec3() {
x = y = z = 0.0f;
}
Vec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f): x(_x), y(_y), z(_z) { }
inline bool equalFloat(const float x, const float y)
{

180
photon_tracer.cpp Normal file
View File

@@ -0,0 +1,180 @@
#include <limits>
#include <glm/gtc/constants.hpp>
#include "photon_tracer.hpp"
#include "sampling.hpp"
#include "area_light.hpp"
using std::numeric_limits;
using namespace glm;
PhotonTracer::~PhotonTracer() { }
vec3 PhotonTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const {
float t, _t;
Figure * _f;
vec3 n, color, i_pos, ref, sample, dir_diff_color, dir_spec_color, ind_color, amb_color;
Ray mv_r, sr, rr;
bool vis, is_area_light = false;
float kr, r1, r2;
AreaLight * al;
t = numeric_limits<float>::max();
_f = NULL;
// Find the closest intersecting surface.
for (size_t f = 0; f < s->m_figures.size(); f++) {
if (s->m_figures[f]->intersect(r, _t) && _t < t) {
t = _t;
_f = s->m_figures[f];
}
}
// If this ray intersects something:
if (_f != NULL) {
// Take the intersection point and the normal of the surface at that point.
i_pos = r.m_origin + (t * r.m_direction);
n = _f->normal_at_int(r, t);
is_area_light = false;
// Check if the object is an area light;
for (vector<Light *>::iterator it = s->m_lights.begin(); it != s->m_lights.end(); it++) {
if ((*it)->light_type() == Light::AREA && static_cast<AreaLight *>(*it)->m_figure == _f)
is_area_light = true;
}
// If the object is an area light, return it's emission value.
if (is_area_light) {
return _f->m_mat->m_emission;
// Check if the material is not reflective/refractive.
} else if (!_f->m_mat->m_refract) {
// Calculate the direct lighting.
for (size_t l = 0; l < s->m_lights.size(); l++) {
// For every light source
vis = true;
if (s->m_lights[l]->light_type() == Light::INFINITESIMAL) {
// Cast a shadow ray to determine visibility.
sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + (n * BIAS));
for (size_t f = 0; f < s->m_figures.size(); f++) {
if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) {
vis = false;
break;
}
}
// Evaluate the shading model accounting for visibility.
dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
} else if (s->m_lights[l]->light_type() == Light::AREA) {
// Cast a shadow ray towards a sample point on the surface of the light source.
al = static_cast<AreaLight *>(s->m_lights[l]);
al->sample_at_surface(i_pos);
sr = Ray(al->direction(i_pos), i_pos + (n * BIAS));
for (size_t f = 0; f < s->m_figures.size(); f++) {
// Avoid self-intersection with the light source.
if (al->m_figure != s->m_figures[f]) {
if (s->m_figures[f]->intersect(sr, _t) && _t < al->distance(i_pos)) {
vis = false;
break;
}
}
}
// Evaluate the shading model accounting for visibility.
dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
}
}
// Calculate indirect lighting contribution.
if (rec_level < m_max_depth) {
r1 = random01();
r2 = random01();
sample = sample_hemisphere(r1, r2);
rotate_sample(sample, n);
rr = Ray(normalize(sample), i_pos + (sample * BIAS));
ind_color += r1 * trace_ray(rr, s, rec_level + 1) / PDF;
}
// Calculate environment light contribution
vis = true;
r1 = random01();
r2 = random01();
sample = sample_hemisphere(r1, r2);
rotate_sample(sample, n);
rr = Ray(normalize(sample), i_pos + (sample * BIAS));
// Cast a shadow ray to determine visibility.
for (size_t f = 0; f < s->m_figures.size(); f++) {
if (s->m_figures[f]->intersect(rr, _t)) {
vis = false;
break;
}
}
amb_color = vis ? s->m_env->get_color(rr) * max(dot(n, rr.m_direction), 0.0f) / PDF : vec3(0.0f);
// Add lighting.
color += ((dir_diff_color + ind_color + amb_color) * (_f->m_mat->m_diffuse / pi<float>())) + (_f->m_mat->m_specular * dir_spec_color);
// Determine the specular reflection color.
if (_f->m_mat->m_rho > 0.0f && rec_level < m_max_depth) {
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
color += _f->m_mat->m_rho * trace_ray(rr, s, rec_level + 1);
} else if (_f->m_mat->m_rho > 0.0f && rec_level >= m_max_depth)
return vec3(0.0f);
} else {
// If the material has transmission enabled, calculate the Fresnel term.
kr = fresnel(r.m_direction, n, r.m_ref_index, _f->m_mat->m_ref_index);
// Determine the specular reflection color.
if (kr > 0.0f && rec_level < m_max_depth) {
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
color += kr * trace_ray(rr, s, rec_level + 1);
} else if (rec_level >= m_max_depth)
return vec3(0.0f);
// Determine the transmission color.
if (_f->m_mat->m_refract && kr < 1.0f && rec_level < m_max_depth) {
rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat->m_ref_index)), i_pos - n * BIAS, _f->m_mat->m_ref_index);
color += (1.0f - kr) * trace_ray(rr, s, rec_level + 1);
} else if (rec_level >= m_max_depth)
return vec3(0.0f);
}
// Return final color.
return _f->m_mat->m_emission + color;
} else
return s->m_env->get_color(r);
}
void PhotonTracer::build_photon_map(kdTree & photon_map, Scene * s, const unsigned int rec_level, const size_t n_photons_per_ligth, const bool specular) const {
Light * l;
Photon photon;
for (vector<Light *>::iterator it = s->m_lights.begin(); it != s->m_lights.end(); it++) {
for (size_t p = 0; p < n_photons_per_ligth; p++) {
l = *it;
if (!specular) {
// TODO: Generate photon from light source.
} else {
// TODO: Generate photon from light source in direction of specular reflective objects.
}
// TODO: Trace indirect illumination for the generated sample.
photon_map.addPhoton(photon);
}
}
}

21
photon_tracer.hpp Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#ifndef PHOTON_TRACER_HPP
#define PHOTON_TRACER_HPP
#include "tracer.hpp"
#include "kd_tree.hpp"
class PhotonTracer: public Tracer {
public:
PhotonTracer(): Tracer() { }
PhotonTracer(unsigned int max_depth): Tracer(max_depth) { };
virtual ~PhotonTracer();
virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const;
void build_photon_map(kdTree & photon_map, Scene * s, const unsigned int rec_level, const size_t n_photons_per_ligth = 10000, const bool specular = false) const;
};
#endif

View File

@@ -1,7 +1,29 @@
#include <cmath>
/* THIS CODE CARRIES NO GUARANTEE OF USABILITY OR FITNESS FOR ANY PURPOSE.
* WHILE THE AUTHORS HAVE TRIED TO ENSURE THE PROGRAM WORKS CORRECTLY,
* IT IS STRICTLY USE AT YOUR OWN RISK. */
/* This file contains code to read and write four byte rgbe file format
developed by Greg Ward. It handles the conversions between rgbe and
pixels consisting of floats. The data is assumed to be an array of floats.
By default there are three floats per pixel in the order red, green, blue.
(RGBE_DATA_??? values control this.) Only the mimimal header reading and
writing is implemented. Each routine does error checking and will return
a status value as defined below. This code is intended as a skeleton so
feel free to modify it to suit your needs.
(Place notice here if you modified the code.)
posted to http://www.graphics.cornell.edu/~bjw/
written by Bruce Walter (bjw@graphics.cornell.edu) 5/26/95
based on code written by Greg Ward
*/
#include <glm/glm.hpp>
#include "rgbe.hpp"
using glm::frexp;
using glm::ldexp;
/* standard conversion from float pixels to rgbe pixels */
/* note: you can remove the "inline"s if your compiler complains about it */
void float2rgbe(unsigned char rgbe[4], float red, float green, float blue) {