diff --git a/out.jpg b/out.jpg index b65225c..5660126 100644 Binary files a/out.jpg and b/out.jpg differ diff --git a/tinyraytracer.cpp b/tinyraytracer.cpp index 0b0e42d..385df3a 100644 --- a/tinyraytracer.cpp +++ b/tinyraytracer.cpp @@ -5,11 +5,18 @@ #include #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; }