aboutsummaryrefslogtreecommitdiff
path: root/src/render.cpp
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2020-08-13 20:06:29 +0200
committerJulian T <julian@jtle.dk>2020-08-13 20:06:29 +0200
commit5b0b916c561f602723b9ae80f5462a7939b652a1 (patch)
tree6ee419f0dd1649b2c329585551f06a555a631db8 /src/render.cpp
parent690b72664ca8d471f5c117f6ed87aeae2de0a208 (diff)
Pathtracing working with defuse and emissive lighting
Diffstat (limited to 'src/render.cpp')
-rw-r--r--src/render.cpp84
1 files changed, 67 insertions, 17 deletions
diff --git a/src/render.cpp b/src/render.cpp
index 197226e..0bbe5cb 100644
--- a/src/render.cpp
+++ b/src/render.cpp
@@ -2,20 +2,59 @@
#include "vector.hpp"
#include "common.hpp"
+#include <cstdlib>
#include <math.h>
#include <iostream>
#define FOV 1.74533
+// Uniform sampling
+#define SAMPLING_POWER 0
+
const Vec3d up = Vec3d(0, 1, 0);
-Renderer::Renderer(const Scene &scn, Vec3d eye, Vec3d target, unsigned width, unsigned height) :
+Sampler::Sampler() {
+ m_seed = 0;
+}
+
+void Sampler::seed(unsigned seed) {
+ for (unsigned i = 0; i < seed; i++) {
+ rand_r(&m_seed);
+ }
+}
+
+double Sampler::random() {
+ return (double)rand_r(&m_seed) / (double)RAND_MAX;
+}
+
+Vec3d Sampler::sample(const Vec3d &norm) {
+ /*
+ auto theta = asin(pow(1 - random(), (double)1 / (1 + SAMPLING_POWER)));
+ auto phi = 2 * M_PI * random();
+ */
+
+ auto theta = 2.0 * M_PI * random();
+ auto phi = acos(2.0 * random() - 1.0);
+
+ auto sinphi = sin(phi);
+
+ auto newvec = Vec3d(cos(theta) * sinphi, sin(theta) * sinphi, cos(phi));
+
+ if (newvec.dot(norm) <= 0) {
+ newvec = -newvec;
+ }
+
+ return newvec;
+}
+
+Renderer::Renderer(const Scene &scn, Vec3d eye, Vec3d target, unsigned width, unsigned height, unsigned maxhops) :
m_scn(scn)
{
m_eye = eye;
m_target = target;
m_width = width;
m_height = height;
+ m_maxhops = maxhops;
recalculate();
}
@@ -48,12 +87,27 @@ Ray Renderer::findray(double x, double y) const {
return Ray(m_eye, dir, true);
}
-Color Renderer::render(unsigned x, unsigned y) {
+Color Renderer::render(unsigned x, unsigned y, unsigned samples) {
auto r = findray(x, y);
- return pathtrace_sample(r, 0);
+
+ Color sum(0, 0, 0);
+
+ for (unsigned i = 0; i < samples; i++) {
+ sum += pathtrace_sample(r, 0);
+ }
+
+ if (samples < 2) {
+ return sum;
+ } else {
+ return Vec3d(sum) / (double)samples;
+ }
}
Color Renderer::pathtrace_sample(const Ray &r, unsigned hop) {
+ if (hop >= m_maxhops) {
+ return Color(0, 0, 0);
+ }
+
double dist;
auto res = cast_ray(r, 0, &dist);
@@ -61,24 +115,20 @@ Color Renderer::pathtrace_sample(const Ray &r, unsigned hop) {
return Color(0, 0, 0);
}
- // Calculate endpoint
- auto end = r.m_start + r.m_direction * dist;
+ auto col = res->m_mat.emits();
+ if (res->m_mat.reflects()) {
+ // Calculate endpoint
+ auto end = r.m_start + r.m_direction * dist;
+ auto norm = res->norm_at(end, r.m_direction);
- auto norm = res->norm_at(end, r.m_direction);
+ auto randdir = m_sampler.sample(norm);
+ auto newray = Ray(end, randdir, true);
+ auto incol = pathtrace_sample(newray, hop+1);
- // Simulate single light
- auto l = Vec3d(0, 7, 0);
-
- auto tolight = l - end;
- auto distance = tolight.length();
- tolight.normalize();
- auto lightray = Ray(end, tolight, false);
-
- if (cast_ray(lightray, distance, nullptr)) {
- return Color(0, 0, 0);
+ col += res->m_mat.reflect(norm, r.m_direction, newray.m_direction, incol);
}
- return res->m_mat.reflect(norm, r.m_direction, tolight);
+ return col;
}
const Shape* Renderer::cast_ray(const Ray &r, double chk_dist, double *dist_ret) {