#include #include #include #include #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, 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; 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; } }; 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 material.diffuse_color; } void render(const std::vector &spheres) { 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 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; }