diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.hpp | 6 | ||||
-rw-r--r-- | src/main.rs | 3 | ||||
-rw-r--r-- | src/object.cpp | 103 | ||||
-rw-r--r-- | src/object.hpp | 76 | ||||
-rw-r--r-- | src/ray.cpp | 17 | ||||
-rw-r--r-- | src/ray.hpp | 15 | ||||
-rw-r--r-- | src/render.cpp | 166 | ||||
-rw-r--r-- | src/render.hpp | 61 | ||||
-rw-r--r-- | src/scene.cpp | 5 | ||||
-rw-r--r-- | src/scene.hpp | 15 | ||||
-rw-r--r-- | src/vector.cpp | 106 | ||||
-rw-r--r-- | src/vector.hpp | 33 |
12 files changed, 3 insertions, 603 deletions
diff --git a/src/common.hpp b/src/common.hpp deleted file mode 100644 index fd219bf..0000000 --- a/src/common.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#define ZERO_APPROX 1e-6 - -#endif diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/object.cpp b/src/object.cpp deleted file mode 100644 index 1449cbb..0000000 --- a/src/object.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "object.hpp" - -#include <math.h> -#include <iostream> -#include "common.hpp" - -void Color::clamp() { - if (m_x > 1) { m_x = 1; } - if (m_y > 1) { m_y = 1; } - if (m_z > 1) { m_z = 1; } -} - -Material::Material(Color color, double defuse, double emissive) { - m_color = color; - m_defuse = defuse; - m_emissive = emissive; -} - -Color Material::reflect(const Vec3d &normal, const Vec3d &in, const Vec3d &out, const Color &incol) const { - return Vec3d(m_color) * m_emissive + - (Vec3d(m_color) * Vec3d(incol)) * (out.dot(normal) * m_defuse); -} - -Sphere::Sphere(const Material &mat, Vec3d center, double radius) : Shape(mat) { - m_center = center; - m_radius = radius; -} - -Plane::Plane(const Material &mat, Vec3d start, Vec3d norm) : Shape(mat) { - m_start = start; - m_norm = norm; - - m_norm.normalize(); -} - -Vec3d Sphere::norm_at(const Vec3d &point, const Vec3d&) const { - auto res = point - m_center; - res.normalize(); - return res; -} - -// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection -double Sphere::intersect(const Ray &ray, bool skip_dist) const { - // Calculate O - C used multiple places - auto oc = ray.m_start - m_center; - // Calculate components of quadratic formula - // a = 1 when ray.direction is a unit vector - auto a = 1; - auto b = 2 * ray.m_direction.dot(oc); - auto c = oc.dot(oc) - m_radius * m_radius; - - // Solve quadratic function - auto discr = b * b - 4 * a * c; - if (discr < 0) { - // No solution - return -1; - } - if (skip_dist) { - // Do not calculate distance - return 1; - } - - auto q = (b > 0) ? - -0.5 * (b + sqrt(discr)): - -0.5 * (b - sqrt(discr)); - auto t1 = q; // Assuming a = 1 - auto t0 = c / q; - - // Find correct result - if (t0 <= ZERO_APPROX) { - t0 = t1; - } - - if (t0 <= ZERO_APPROX) { - return -1; - } - - return t0; -} - -Vec3d Plane::norm_at(const Vec3d&, const Vec3d &indir) const { - auto scale = m_norm.dot(indir); - return scale > 0 ? -m_norm : m_norm; -} - -// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-plane-and-ray-disk-intersection -// Requires that vectors are normalized -// Skip dist is ignored as distance must be calculated -double Plane::intersect(const Ray &ray, bool) const { - // If ray is parallel - auto nr = m_norm.dot(ray.m_direction); - if (abs(nr) < ZERO_APPROX) { - return -1; - } - - // Calculate distance - auto dist = m_norm.dot(m_start - ray.m_start) / nr; - if (dist < 0) { - return -1; - } - - return dist; -} diff --git a/src/object.hpp b/src/object.hpp deleted file mode 100644 index e697ba2..0000000 --- a/src/object.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef OBJECT_H -#define OBJECT_H - -#include <memory> -#include "vector.hpp" -#include "ray.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; } - - Color& operator+=(const Color& op) { - Vec3d::operator+=(op); - return *this; - } - void clamp(); -}; - -// Implements phong BRDF -class Material { - public: - Material(Color color, double defuse, double emissive=0); - - Color reflect(const Vec3d &normal, const Vec3d &in, const Vec3d &out, const Color &incol) const; - - Color emits() const { - return m_color * m_emissive; - } - - // Whether the material is reflective - bool reflects() const { return m_defuse > 0; } - private: - Color m_color; - double m_defuse; - double m_emissive; -}; - -class Shape { - public: - Shape(const Material &mat) : m_mat(mat) { } - - virtual Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const = 0; - virtual double intersect(const Ray &ray, bool skip_dist) const = 0; - - const Material &m_mat; -}; - -class Sphere : public Shape { - public: - Sphere(const Material &mat, Vec3d center, double radius); - Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const; - double intersect(const Ray &ray, bool skip_dist) const; - - private: - Vec3d m_center; - double m_radius; -}; - -class Plane : public Shape { - public: - Plane(const Material &mat, Vec3d start, Vec3d norm); - Vec3d norm_at(const Vec3d &point, const Vec3d &indir) const; - double intersect(const Ray &ray, bool skip_dist) const; - - private: - Vec3d m_start; - Vec3d m_norm; -}; - -#endif diff --git a/src/ray.cpp b/src/ray.cpp deleted file mode 100644 index 7bc6201..0000000 --- a/src/ray.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "ray.hpp" - -Ray::Ray(Vec3d start, Vec3d direction, bool normalize) { - m_start = start; - m_direction = direction; - - if (normalize) { - m_direction.normalize(); - } -} - -Ray::Ray(Vec3d a, Vec3d b) { - m_start = a; - m_direction = b - a; - - m_direction.normalize(); -} diff --git a/src/ray.hpp b/src/ray.hpp deleted file mode 100644 index 6341d44..0000000 --- a/src/ray.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef RAY_H -#define RAY_H - -#include "vector.hpp" - -class Ray { - public: - Ray(Vec3d start, Vec3d direction, bool normalize); - Ray(Vec3d a, Vec3d b); - - Vec3d m_start; - Vec3d m_direction; -}; - -#endif diff --git a/src/render.cpp b/src/render.cpp deleted file mode 100644 index c278797..0000000 --- a/src/render.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "render.hpp" -#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); - -void Random::seed(unsigned seed) { - for (unsigned i = 0; i < seed; i++) { - rand_r(&m_seed); - } -} - -double Random::operator()() { - return (double)rand_r(&m_seed) / (double)RAND_MAX; -} - -Sampler::Sampler(Random &src) : m_src(src) { } - -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 * m_src(); - auto phi = acos(2.0 * m_src() - 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_sampler(m_random), - m_scn(scn) -{ - m_eye = eye; - m_target = target; - m_width = width; - m_height = height; - m_maxhops = maxhops; - - 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, unsigned samples) { - - Color sum(0, 0, 0); - - for (unsigned i = 0; i < samples; i++) { - auto r = findray(x + m_random(), y + m_random()); - 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); - - if (!res) { - return Color(0, 0, 0); - } - - 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 randdir = m_sampler.sample(norm); - auto newray = Ray(end, randdir, true); - auto incol = pathtrace_sample(newray, hop+1); - - col += res->m_mat.reflect(norm, r.m_direction, newray.m_direction, incol); - } - - return col; -} - -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 deleted file mode 100644 index 7557fce..0000000 --- a/src/render.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef RENDER_H -#define RENDER_H - -#include "vector.hpp" -#include "ray.hpp" -#include "scene.hpp" - -class Random { - public: - void seed(unsigned seed); - double operator()(); - - private: - unsigned m_seed; -}; - -// Samples a random direction in a hemisphere, cosine weighed -// https://blog.thomaspoulet.fr/uniform-sampling-on-unit-hemisphere/ -class Sampler { - public: - Sampler(Random &src); - - Vec3d sample(const Vec3d &norm); - - private: - Random &m_src; -}; - -class Renderer { - public: - Renderer(const Scene &scn, Vec3d eye, Vec3d target, unsigned width, unsigned height, unsigned maxhops); - - Color render(unsigned x, unsigned y, unsigned samples); - - unsigned m_width, m_height; - Sampler m_sampler; - - 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; - - Random m_random; - - // User options - Vec3d m_eye, m_target; - unsigned m_maxhops; - - // Calculated values - Vec3d m_qx, m_qy, m_blc; - -}; - -#endif diff --git a/src/scene.cpp b/src/scene.cpp deleted file mode 100644 index a8c0695..0000000 --- a/src/scene.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "scene.hpp" - -void Scene::addShape(const Shape *obj) { - objs.push_back(obj); -} diff --git a/src/scene.hpp b/src/scene.hpp deleted file mode 100644 index f270409..0000000 --- a/src/scene.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SCENE_H -#define SCENE_H - -#include <vector> -#include "object.hpp" - -class Scene { - public: - void addShape(const Shape *obj); - - std::vector<const Shape*> objs; - -}; - -#endif diff --git a/src/vector.cpp b/src/vector.cpp deleted file mode 100644 index 51d8e2e..0000000 --- a/src/vector.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "vector.hpp" - -#include <math.h> -#include <stdexcept> - -Vec3d::Vec3d() { - set(0, 0, 0); -} - -Vec3d::Vec3d(double x, double y, double z) { - set(x, y, z); -} - -void Vec3d::set(double x, double y, double z) { - m_x = x; - m_y = y; - m_z = z; -} - -void Vec3d::normalize() { - auto len = length(); - if (len == 0) { - throw std::runtime_error("Normalizing zero vector"); - } - - m_x /= len; - m_y /= len; - m_z /= len; -} - -double Vec3d::length() const { - return sqrt(m_x * m_x + m_y * m_y + m_z * m_z); -} - -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) { - m_x += vec.m_x; - m_y += vec.m_y; - m_z += vec.m_z; - return *this; -} - -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 { - return Vec3d( - -m_x, - -m_y, - -m_z - ); -} - - -Vec3d Vec3d::operator*(double op) const { - return Vec3d( - m_x * op, - m_y * op, - m_z * op - ); -} - -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/(double op) const { - return Vec3d( - m_x / op, - m_y / op, - m_z / op - ); -} - -std::ostream& operator<<(std::ostream &out, const Vec3d &v){ - out << "[ " << v.m_x << ", " << v.m_y << ", " << v.m_z << " ]"; - return out; -} diff --git a/src/vector.hpp b/src/vector.hpp deleted file mode 100644 index 20e8210..0000000 --- a/src/vector.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef VECTOR_H -#define VECTOR_H - -#include <iostream> - -class Vec3d { - public: - Vec3d(); - Vec3d(double x, double y, double z); - - void set(double x, double y, double z); - void normalize(); - - double length() const; - double dot(const Vec3d &vec) const; - - Vec3d cross(const Vec3d &vec) const; - - // Operators - Vec3d operator+(const Vec3d &vec) const; - Vec3d& operator+=(const Vec3d &vec); - Vec3d operator-(const Vec3d &vec) const; - Vec3d operator-() const; - Vec3d operator*(double) const; - Vec3d operator*(const Vec3d &vec) const; - Vec3d operator/(double) const; - - friend std::ostream& operator<<(std::ostream& os, const Vec3d &v); - - double m_x, m_y, m_z; -}; - -#endif |