From c41297b0746aa510348ee2d8f8a8fe32b8434afc Mon Sep 17 00:00:00 2001 From: K Tyl Date: Sun, 7 Jun 2020 04:13:39 +0100 Subject: [PATCH] camera lens + random scene --- src/camera.h | 44 +++++++++++++++++------- src/main.cpp | 97 ++++++++++++++++++++++++++++++++++++---------------- src/vec3.h | 10 ++++++ 3 files changed, 110 insertions(+), 41 deletions(-) diff --git a/src/camera.h b/src/camera.h index 85bc568..06cbd47 100644 --- a/src/camera.h +++ b/src/camera.h @@ -5,22 +5,40 @@ class camera { public: - const double ASPECT_RATIO = 16.0 / 9.0; - const double VIEWPORT_HEIGHT = 2.0; - const double VIEWPORT_WIDTH = ASPECT_RATIO * VIEWPORT_HEIGHT; - const double FOCAL_LENGTH = 1.0; - - camera() : - origin_ (point3(0,0,0)), - horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)), - vertical_ (vec3(0.0, VIEWPORT_HEIGHT, 0.0)) + camera( + point3 lookfrom, + point3 lookat, + vec3 vup, + double vfov, // vertical field of view in degrees + double aspect_ratio, + double aperture, + double focus_dist) { - lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH); + auto theta = degrees_to_radians(vfov); + auto h = tan(theta/2); + auto viewport_height = 2.0 * h; + auto viewport_width = aspect_ratio * viewport_height; + + w_ = unit_vector(lookfrom - lookat); + u_ = unit_vector(cross(vup, w_)); + v_ = cross(w_, u_); + + origin_ = lookfrom; + horizontal_ = focus_dist * viewport_width * u_; + vertical_ = focus_dist * viewport_height * v_; + lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_; + + lens_radius_ = aperture / 2; } - ray get_ray(double u, double v) const + ray get_ray(double s, double t) const { - return ray(origin_, lower_left_corner_ + u*horizontal_ + v*vertical_ - origin_); + vec3 rd = lens_radius_ * random_in_unit_disk(); + vec3 offset = (u_ * rd.x()) + (v_ * rd.y()); + + return ray( + origin_ + offset, + lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset); } private: @@ -28,4 +46,6 @@ class camera point3 lower_left_corner_; vec3 horizontal_; vec3 vertical_; + vec3 u_, v_, w_; + double lens_radius_; }; diff --git a/src/main.cpp b/src/main.cpp index c0b2e20..ece418c 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,11 +8,11 @@ #include -const double ASPECT_RATIO = 16.0 / 9.0; -const int WIDTH = 384; +const double ASPECT_RATIO = 32.0 / 9.0; +const int WIDTH = 800; const int HEIGHT = static_cast(WIDTH / ASPECT_RATIO); -const int SAMPLES_PER_PIXEL = 100; -const int MAX_DEPTH = 50; +const int SAMPLES_PER_PIXEL = 32; +const int MAX_DEPTH = 16; colour ray_colour(const ray& r, const hittable& world, int depth) { @@ -38,41 +38,80 @@ colour ray_colour(const ray& r, const hittable& world, int depth) vec3 unit_direction = unit_vector(r.direction()); auto t = 0.5 * (unit_direction.y() + 1.0); - auto a = colour(0.5, 0.6, 0.7); - auto b = colour(0.5, 0.5, 0.5); + auto a = colour(0.8, 0.7, 1.0); + auto b = colour(1.0, 1.0, 1.0); return lerp(a, b, t); } +hittable_list random_scene() +{ + hittable_list world; + + auto ground_material = make_shared(colour(0.5, 0.5, 0.5)); + world.add(make_shared(point3(0,-1000,0), 1000, ground_material)); + + for (int a = -11; a < 11; a++) + { + for (int b = -11; b < 11; b++) + { + auto choose_mat = random_double(); + point3 centre(a + 0.9*random_double(), 0.2, b + 0.9*random_double()); + + if ((centre - point3(4, 0.2, 0)).length() > 0.9) + { + shared_ptr sphere_material; + + if (choose_mat < 0.8) + { + // diffuse + auto albedo = colour::random() * colour::random(); + sphere_material = make_shared(albedo); + world.add(make_shared(centre, 0.2, sphere_material)); + } + else if (choose_mat < 0.95) + { + // metal + auto albedo = colour::random(0.5, 1); + auto fuzz = random_double(0, 0.5); + sphere_material = make_shared(albedo, fuzz); + world.add(make_shared(centre, 0.2, sphere_material)); + } + else + { + // glass + sphere_material = make_shared(1.5); + world.add(make_shared(centre,0.2, sphere_material)); + } + } + } + } + + auto material1 = make_shared(1.5); + world.add(make_shared(point3(0, 1, 0), 1.0, material1)); + + auto material2 = make_shared(colour(0.4, 0.2, 0.1)); + world.add(make_shared(point3(-4, 1, 0), 1.0, material2)); + + auto material3 = make_shared(colour(0.7, 0.6, 0.5), 0.0); + world.add(make_shared(point3(4, 1, 0), 1.0, material3)); + + return world; +} + int main() { std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; - hittable_list world; - - world.add(make_shared( - point3(0,0,-1), - 0.5, - make_shared(colour(0.1,0.2,0.5)))); - world.add(make_shared( - point3(0,-100.5,-1), - 100, - make_shared(colour(0.8,0.8,0.0)))); + hittable_list world = random_scene(); - world.add(make_shared( - point3(1,0,-1), - 0.5, - make_shared(colour(0.8,0.6,0.2), 0.0))); - world.add(make_shared( - point3(-1,0,-1), - 0.5, - make_shared(1.5))); - world.add(make_shared( - point3(-1,0,-1), - -0.45, - make_shared(1.5))); + point3 lookfrom(13,2,3); + point3 lookat(0,0,0); + vec3 vup(0,1,0); + auto dist_to_focus = 10.0; + auto aperture = 0.1; - camera cam; + camera cam(lookfrom, lookat, vup, 20, ASPECT_RATIO, aperture, dist_to_focus); for (int j = HEIGHT - 1; j >= 0; --j) { diff --git a/src/vec3.h b/src/vec3.h index c47ff8f..d76dcff 100755 --- a/src/vec3.h +++ b/src/vec3.h @@ -160,6 +160,16 @@ vec3 random_in_hemisphere(const vec3& normal) } } +vec3 random_in_unit_disk() +{ + while(true) + { + auto p = vec3(random_double(-1,1), random_double(-1,1), 0); + if (p.length_squared() >= 1) continue; + return p; + } +} + vec3 reflect(const vec3& v, const vec3& n) { return v - 2*dot(v,n)*n;