aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2020-08-06 19:21:49 +0200
committerJulian T <julian@jtle.dk>2020-08-06 19:22:37 +0200
commit4348cc9581bfea05359485c5d2d074132d0271da (patch)
tree0c6d92a90ac4cf9acd326f632dcdc962ddca013a /src
parent893176a0b18a2281abe09def716ccc3db5583c3f (diff)
Renders scenes with a single hardcoded light and green objects
Diffstat (limited to 'src')
-rw-r--r--src/object.cpp5
-rw-r--r--src/object.hpp8
-rw-r--r--src/render.cpp124
-rw-r--r--src/render.hpp50
-rw-r--r--src/scene.cpp4
-rw-r--r--src/scene.hpp4
-rw-r--r--src/vector.cpp27
-rw-r--r--src/vector.hpp2
8 files changed, 210 insertions, 14 deletions
diff --git a/src/object.cpp b/src/object.cpp
index e88ae13..179785a 100644
--- a/src/object.cpp
+++ b/src/object.cpp
@@ -1,6 +1,7 @@
#include "object.hpp"
#include <math.h>
+#include <iostream>
#include "common.hpp"
Sphere::Sphere(Vec3d center, double radius) {
@@ -15,10 +16,6 @@ Plane::Plane(Vec3d start, Vec3d norm) {
m_norm.normalize();
}
-void Object::setMaterial(std::shared_ptr<Material> m) {
- m_mat = m;
-}
-
Vec3d Sphere::norm_at(const Vec3d &point, const Vec3d&) const {
auto res = point - m_center;
res.normalize();
diff --git a/src/object.hpp b/src/object.hpp
index 3194dac..ac5122f 100644
--- a/src/object.hpp
+++ b/src/object.hpp
@@ -8,17 +8,15 @@
class Material {
};
-class Object {
+class Shape {
public:
void setMaterial(std::shared_ptr<Material> m);
- std::shared_ptr<Material> m_mat;
-
virtual Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const = 0;
virtual double intersect(const Ray &ray, bool skip_dist) const = 0;
};
-class Sphere : Object {
+class Sphere : public Shape {
public:
Sphere(Vec3d center, double radius);
Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const;
@@ -29,7 +27,7 @@ class Sphere : Object {
double m_radius;
};
-class Plane : Object {
+class Plane : public Shape {
public:
Plane(Vec3d start, Vec3d norm);
Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const;
diff --git a/src/render.cpp b/src/render.cpp
new file mode 100644
index 0000000..5601863
--- /dev/null
+++ b/src/render.cpp
@@ -0,0 +1,124 @@
+#include "render.hpp"
+#include "vector.hpp"
+#include "common.hpp"
+
+#include <math.h>
+#include <iostream>
+
+#define FOV 1.74533
+
+const Vec3d up = Vec3d(0, 1, 0);
+
+void Color::clamp() {
+ if (m_x > 1) { m_x = 1; }
+ if (m_y > 1) { m_y = 1; }
+ if (m_z > 1) { m_z = 1; }
+}
+
+Renderer::Renderer(const Scene &scn, Vec3d eye, Vec3d target, unsigned width, unsigned height) :
+ m_scn(scn)
+{
+ m_eye = eye;
+ m_target = target;
+ m_width = width;
+ m_height = height;
+
+ recalculate();
+}
+
+void Renderer::recalculate() {
+ auto tmp = m_target - m_eye;
+
+ // Orthogonal vector to E
+ auto b = up.cross(tmp);
+
+ b.normalize();
+ tmp.normalize();
+
+ auto v = tmp.cross(b);
+
+ // Calculate size of viewplane
+ double gx = tan( FOV / 2);
+ double gy = gx * ((double) m_height / m_width);
+
+ // Calculate scaling vectors
+ m_qx = b * ((2 * gx) / (m_width - 1));
+ m_qy = v * ((2 * gy) / (m_height - 1));
+
+ // Calculate starting point
+ m_blc = tmp - (b * gx) - (v * gy);
+}
+
+Ray Renderer::findray(double x, double y) const {
+ auto dir = m_blc + (m_qx * x) + (m_qy * y);
+ return Ray(m_eye, dir, true);
+}
+
+Color Renderer::render(unsigned x, unsigned y) {
+ auto r = findray(x, y);
+ return pathtrace_sample(r, 0);
+}
+
+Color Renderer::pathtrace_sample(const Ray &r, unsigned hop) {
+ double dist;
+ auto res = cast_ray(r, 0, &dist);
+
+ if (!res) {
+ return Color(0, 0, 0);
+ }
+
+ // Calculate endpoint
+ auto end = r.m_start + r.m_direction * dist;
+
+ auto norm = res->norm_at(end, r.m_direction);
+
+ // 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);
+ }
+
+ auto green = Color(0, 1, 0);
+ return Color(green * norm.dot(tolight));
+}
+
+const Shape* Renderer::cast_ray(const Ray &r, double chk_dist, double *dist_ret) {
+ const Shape *smallest = nullptr;
+ double dist = 0;
+
+ for (auto obj : m_scn.objs) {
+ if (!obj) {
+ continue;
+ }
+ auto d = obj->intersect(r, false);
+ if (d > ZERO_APPROX) {
+ if (chk_dist > 0 && d < chk_dist) {
+ dist = d; smallest = obj;
+ goto exit;
+ }
+ if (d < dist || smallest == nullptr) {
+ dist = d; smallest = obj;
+ }
+ }
+ }
+
+ if (chk_dist > 0) {
+ // If we reach this it means none of the
+ // object where within distance.
+ return nullptr;
+ }
+
+exit:
+
+ if (dist_ret) {
+ *dist_ret = dist;
+ }
+
+ return smallest;
+}
diff --git a/src/render.hpp b/src/render.hpp
new file mode 100644
index 0000000..3fd84b1
--- /dev/null
+++ b/src/render.hpp
@@ -0,0 +1,50 @@
+#ifndef RENDER_H
+#define RENDER_H
+
+#include "vector.hpp"
+#include "ray.hpp"
+#include "scene.hpp"
+
+class Color : public Vec3d {
+ public:
+ Color() {}
+ Color(const Vec3d &v) : Vec3d(v) {}
+ Color(double r, double g, double b) : Vec3d(r, g, b) {}
+
+ uint8_t r() { return m_x * 255; }
+ uint8_t g() { return m_y * 255; }
+ uint8_t b() { return m_z * 255; }
+
+ void clamp();
+
+};
+
+class Renderer {
+ public:
+ Renderer(const Scene &scn, Vec3d eye, Vec3d target, unsigned width, unsigned height);
+
+ Color render(unsigned x, unsigned y);
+
+ unsigned m_width, m_height;
+
+ private:
+ void recalculate();
+ Ray findray(double x, double y) const ;
+
+ Color pathtrace_sample(const Ray &r, unsigned hop);
+ // Will return first result less than chk_dist.
+ // This is ignored if chk_dist is 0.
+ // If dist is non-null the resulting distance is written here.
+ const Shape* cast_ray(const Ray &r, double chk_dist, double *dist);
+
+ const Scene &m_scn;
+
+ // User options
+ Vec3d m_eye, m_target;
+
+ // Calculated values
+ Vec3d m_qx, m_qy, m_blc;
+
+};
+
+#endif
diff --git a/src/scene.cpp b/src/scene.cpp
index d866fe4..a8c0695 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1,5 +1,5 @@
#include "scene.hpp"
-void Scene::addObject(Object &obj) {
- objs.push_back(&obj);
+void Scene::addShape(const Shape *obj) {
+ objs.push_back(obj);
}
diff --git a/src/scene.hpp b/src/scene.hpp
index a06ccb4..f270409 100644
--- a/src/scene.hpp
+++ b/src/scene.hpp
@@ -6,9 +6,9 @@
class Scene {
public:
- void addObject(Object &obj);
+ void addShape(const Shape *obj);
- std::vector<Object*> objs;
+ std::vector<const Shape*> objs;
};
diff --git a/src/vector.cpp b/src/vector.cpp
index 070f956..1e4f5a1 100644
--- a/src/vector.cpp
+++ b/src/vector.cpp
@@ -1,6 +1,7 @@
#include "vector.hpp"
#include <math.h>
+#include <stdexcept>
Vec3d::Vec3d() {
set(0, 0, 0);
@@ -19,7 +20,7 @@ void Vec3d::set(double x, double y, double z) {
void Vec3d::normalize() {
auto len = length();
if (len == 0) {
- throw "Normalizing zero vector";
+ throw std::runtime_error("Normalizing zero vector");
}
m_x /= len;
@@ -35,6 +36,22 @@ double Vec3d::dot(const Vec3d &vec) const {
return m_x * vec.m_x + m_y * vec.m_y + m_z * vec.m_z;
}
+Vec3d Vec3d::cross(const Vec3d &vec) const {
+ return Vec3d(
+ m_y * vec.m_z - m_z * vec.m_y,
+ m_z * vec.m_x - m_x * vec.m_z,
+ m_x * vec.m_y - m_y * vec.m_x
+ );
+}
+
+Vec3d Vec3d::operator+(const Vec3d &vec) const {
+ return Vec3d(
+ m_x + vec.m_x,
+ m_y + vec.m_y,
+ m_z + vec.m_z
+ );
+}
+
Vec3d Vec3d::operator-(const Vec3d &vec) const {
return Vec3d(
m_x - vec.m_x,
@@ -51,3 +68,11 @@ Vec3d Vec3d::operator-() const {
);
}
+
+Vec3d Vec3d::operator*(double op) const {
+ return Vec3d(
+ m_x * op,
+ m_y * op,
+ m_z * op
+ );
+}
diff --git a/src/vector.hpp b/src/vector.hpp
index 76eb883..05de25c 100644
--- a/src/vector.hpp
+++ b/src/vector.hpp
@@ -15,8 +15,10 @@ class Vec3d {
Vec3d cross(const Vec3d &vec) const;
// Operators
+ Vec3d operator+(const Vec3d &vec) const;
Vec3d operator-(const Vec3d &vec) const;
Vec3d operator-() const;
+ Vec3d operator*(double) const;
double m_x, m_y, m_z;
};