From 5806eb45e93dab225ab335824cbc3f537d511b28 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Sokolov" Date: Sun, 20 Jan 2019 12:15:18 +0100 Subject: [PATCH] The crucial step: casting the rays + ray/sphere intersection routine --- out.jpg | Bin 47293 -> 14957 bytes tinyraytracer.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/out.jpg b/out.jpg index 870bea92825a55e32629229830ee5ea7792c8b22..b65225c512095e0d075ae7a3099b1a48a08c6c42 100644 GIT binary patch literal 14957 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 diff --git a/tinyraytracer.cpp b/tinyraytracer.cpp index 477835e..0b0e42d 100644 --- a/tinyraytracer.cpp +++ b/tinyraytracer.cpp @@ -5,14 +5,48 @@ #include #include "geometry.h" -void render() { +struct Sphere { + Vec3f center; + float radius; + + Sphere(const Vec3f &c, const float &r) : center(c), radius(r) {} + + bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const { + Vec3f L = center - orig; + float tca = L*dir; + float d2 = L*L - tca*tca; + if (d2 > radius*radius) return false; + float thc = sqrtf(radius*radius - d2); + t0 = tca - thc; + float t1 = tca + thc; + if (t0 < 0) t0 = t1; + if (t0 < 0) return false; + return true; + } +}; + +Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const Sphere &sphere) { + float sphere_dist = std::numeric_limits::max(); + if (!sphere.ray_intersect(orig, dir, sphere_dist)) { + return Vec3f(0.2, 0.7, 0.8); // background color + } + + return Vec3f(0.4, 0.4, 0.3); +} + +void render(const Sphere &sphere) { const int width = 1024; const int height = 768; + const int fov = M_PI/2.; std::vector framebuffer(width*height); + #pragma omp parallel for for (size_t j = 0; j