diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
commit | db072ad4dc181eca5a1458656b130beb43f475bf (patch) | |
tree | a3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/pathtracing.cpp | |
download | csci427-master.tar.xz csci427-master.zip |
Diffstat (limited to 'hw6/src/pathtracing.cpp')
-rw-r--r-- | hw6/src/pathtracing.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/hw6/src/pathtracing.cpp b/hw6/src/pathtracing.cpp new file mode 100644 index 0000000..dc9dda1 --- /dev/null +++ b/hw6/src/pathtracing.cpp @@ -0,0 +1,175 @@ +/******************************************************************/ +/* This file is part of the homework assignments for CSCI-427/527 */ +/* at The College of William & Mary and authored by Pieter Peers. */ +/* No part of this file, whether altered or in original form, can */ +/* be distributed or used outside the context of CSCI-427/527 */ +/* without consent of either the College of William & Mary or */ +/* Pieter Peers. */ +/******************************************************************/ +#include "ray_util.h" +#include "pathtracing.h" +#include "random_number.h" + +////////////////// +// Constructors // +////////////////// +pathtracing::pathtracing(unsigned int samplesPerPixel, bool directOnly) +{ + _samples = samplesPerPixel; + _directOnly = directOnly; +} + + +///////////// +// Methods // +///////////// +image pathtracing::render(const scene& s) const +{ + image result(s.getCamera().width(), s.getCamera().height()); + + // for every pixel + for(image::size_type y=0; y < result.height(); y++) + for(image::size_type x=0; x < result.width(); x++) + { + color pixelRadiance(0.0f, 0.0f, 0.0f); + + // for every sample + for(unsigned int sample = 0; sample < _samples; sample++) + { + color sampleRadiance(0.0f, 0.0f, 0.0f); + + // generate random camera ray through pixel: + float px = (float)(x) + random_float(); float py = (float)(y) + random_float(); + ray r = s.getCamera()(px, py); + + // get initial intersection point + intersectionPoint ip = s.intersect(r); + + // get radiance from directly visible *area* light sources + if(ip.isHit()) + sampleRadiance += ip.emittance(); + + // get scene radiance + sampleRadiance += radiance(s, r, ip); + + // store + pixelRadiance += sampleRadiance / (float)(_samples); + } + + // store in image + result(x,y) = pixelRadiance; + } + + // Done. + return result; +} + + +///////////////////// +// Private Methods // +///////////////////// +color pathtracing::radiance(const scene& s, const ray& r, const intersectionPoint& ip) const +{ + color radiance(0.0f, 0.0f, 0.0f); + + // if scene hit + if(ip.isHit()) + { + // solve rendering equation + radiance = directRadiance(s, ip); + if(!_directOnly) radiance += indirectRadiance(s, ip); + } + + // if not hit + else if(s.hasEnvironmentMap()) + { + radiance += s.evaluateEnvironmentMap(r.direction()); + } + + // Done. + return radiance; +} + + +color pathtracing::directRadiance(const scene& s, const intersectionPoint& ip) const +{ + // HW6: implement this. Compute the direct radiance incident + // at the intersection point 'ip' according to the + // rendering equation. + // Modifies: nothing + // Returns: computed direct radiance. + + color result = color(0.0f); + + // for every light source, + for (int l = 0; l < s.numberOfLightsources(); l++) { + // sample the light source + lightSample ls = s.getLightsource(l).emittanceAt(ip.position(), random_float(), random_float()); + + // check if occluded + ray shadowRay = createRay(ip, ls.directionToLight()); + intersectionPoint shadowIp = s.intersect(shadowRay); + + // if not occluded, + if (ls < shadowIp && ls.distance() > sqrt(EPSILON)) { + float cosine = ls.directionToLight().dot(ip.normal()) / ls.distance(); + + // if no division by zero, + if (ls.pdf() > EPSILON && cosine >= 0) { + // compute radiance via rendering equation for direct illumination + result += (ip.reflectance(ls.directionToLight()) // fr(x, -psi<->theta) (brdf) + * ls.emittance() // Le(y->psi) + * cosine // cos(nx, -psi) + * ls.foreshortening() // cos(ny, psi) + / ls.distance() // r^2 (other r in cosine calculation) + / ls.pdf() // pdf (monte-carlo integration probability) + ); + } + + } + + } + + return result; +} + + +color pathtracing::indirectRadiance(const scene& s, const intersectionPoint& ip) const +{ + // HW6: implement this. Computed the indirect radiance incident + // at the intersection point 'ip' according to the rendering + // equation. + // Modifies: nothing + // Returns: computed indirect radiance. + + color result = color(0.0f); + + // if absorption falls above a random value, end recursion (russian roulette) + if (1 - ip.reflectivity() > random_float(1.0f)) { return result; } + + // sample the surface + brdfSample brdf = ip.sample(random_float(), random_float()); + + // create exitant ray + ray exitantRay = createRay(ip, brdf.exitantDirection()); + + // recursively compute radiance from reflected point + color reflectedColor = radiance(s, exitantRay, s.intersect(exitantRay)); + + // compute cosine + float cosine = brdf.exitantDirection().dot(ip.normal()); + + // if no division by zero via pdf and cosines are not negative, + if (brdf.pdf() > EPSILON && cosine > EPSILON) { + // compute radiance via rendering equation for indirect illumination + result += (brdf.reflectance() // fr(x, -psi<->theta) (brdf) + * reflectedColor // Le(y->psi) + * cosine // cos(nx, -psi) + / brdf.pdf() // pdf (monte-carlo integration probability) + / ip.reflectivity() // russian roulette + ); + + } + + return result; +} |