From c19c430151cb659372b4988876173b022164e371 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Sokolov" Date: Sun, 20 Jan 2019 12:16:23 +0100 Subject: [PATCH] adding more spheres to the scene; rudimentary materials --- out.jpg | Bin 14957 -> 34411 bytes tinyraytracer.cpp | 49 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/out.jpg b/out.jpg index b65225c512095e0d075ae7a3099b1a48a08c6c42..56601262a265b36f3386c2312b21d17be1fbbed5 100644 GIT binary patch literal 34411 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 #include "geometry.h" +struct Material { + Material(const Vec3f &color) : diffuse_color(color) {} + Material() : diffuse_color() {} + Vec3f diffuse_color; +}; + struct Sphere { Vec3f center; float radius; + Material material; - Sphere(const Vec3f &c, const float &r) : center(c), radius(r) {} + Sphere(const Vec3f &c, const float &r, const Material &m) : center(c), radius(r), material(m) {} bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const { Vec3f L = center - orig; @@ -25,16 +32,32 @@ struct Sphere { } }; -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)) { +bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres, Vec3f &hit, Vec3f &N, Material &material) { + float spheres_dist = std::numeric_limits::max(); + for (size_t i=0; i < spheres.size(); i++) { + float dist_i; + if (spheres[i].ray_intersect(orig, dir, dist_i) && dist_i < spheres_dist) { + spheres_dist = dist_i; + hit = orig + dir*dist_i; + N = (hit - spheres[i].center).normalize(); + material = spheres[i].material; + } + } + return spheres_dist<1000; +} + +Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres) { + Vec3f point, N; + Material material; + + if (!scene_intersect(orig, dir, spheres, point, N, material)) { return Vec3f(0.2, 0.7, 0.8); // background color } - return Vec3f(0.4, 0.4, 0.3); + return material.diffuse_color; } -void render(const Sphere &sphere) { +void render(const std::vector &spheres) { const int width = 1024; const int height = 768; const int fov = M_PI/2.; @@ -46,7 +69,7 @@ void render(const Sphere &sphere) { float x = (2*(i + 0.5)/(float)width - 1)*tan(fov/2.)*width/(float)height; float y = -(2*(j + 0.5)/(float)height - 1)*tan(fov/2.); Vec3f dir = Vec3f(x, y, -1).normalize(); - framebuffer[i+j*width] = cast_ray(Vec3f(0,0,0), dir, sphere); + framebuffer[i+j*width] = cast_ray(Vec3f(0,0,0), dir, spheres); } } @@ -62,8 +85,16 @@ void render(const Sphere &sphere) { } int main() { - Sphere sphere(Vec3f(-3, 0, -16), 2); - render(sphere); + Material ivory(Vec3f(0.4, 0.4, 0.3)); + Material red_rubber(Vec3f(0.3, 0.1, 0.1)); + + std::vector spheres; + spheres.push_back(Sphere(Vec3f(-3, 0, -16), 2, ivory)); + spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, red_rubber)); + spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber)); + spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, ivory)); + + render(spheres); return 0; }