From 3b567beadb6275adf4b60e1eca003e44014c3786 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Tue, 22 Dec 2020 23:19:59 +0100 Subject: Defocus blur & randow scene generation --- include/camera.hpp | 14 +++++++++++- include/vec3.hpp | 2 ++ src/camera.cpp | 30 ++++++++++++++++-------- src/main.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++------------ src/vec3.cpp | 8 +++++++ 5 files changed, 96 insertions(+), 25 deletions(-) diff --git a/include/camera.hpp b/include/camera.hpp index 0b3d20e..88ece6f 100644 --- a/include/camera.hpp +++ b/include/camera.hpp @@ -5,15 +5,27 @@ class camera { public: - camera(point3 position, point3 target, double v_fov, double aspect_ratio); + camera( + point3 position, + point3 target, + double v_fov, + double aspect_ratio, + double aperture, + double focus_dist + ); ray get_ray(double u, double v) const; point3 position; + double lens_radius; vec3 horizontal; vec3 vertical; + vec3 forward; + vec3 right; + vec3 up; + point3 bottom_left_pixel; }; diff --git a/include/vec3.hpp b/include/vec3.hpp index 7d38472..4bed1b0 100644 --- a/include/vec3.hpp +++ b/include/vec3.hpp @@ -63,6 +63,8 @@ vec3 random_unit_vector(); vec3 random_in_hemisphere(const vec3& normal); +vec3 random_in_unit_disk(); + using point3 = vec3; using color = vec3; diff --git a/src/camera.cpp b/src/camera.cpp index 520cc1e..c7866d6 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -2,27 +2,37 @@ #include "rt.hpp" -camera::camera(point3 position, point3 target, double v_fov, double aspect_ratio) - : position(position) { +camera::camera( + point3 position, + point3 target, + double v_fov, + double aspect_ratio, + double aperture, + double focus_dist + ) : position(position), lens_radius(aperture / 2.0) { - auto forward = (position - target).unit(); - auto right = vec3{ 0.0, 1.0, 0.0 }.cross(forward).unit(); - auto up = forward.cross(right).unit(); + forward = (position - target).unit(); + right = vec3{ 0.0, 1.0, 0.0 }.cross(forward).unit(); + up = forward.cross(right).unit(); auto h = tan(deg_to_rad(v_fov) / 2.0); auto viewport_height = 2.0 * h; auto viewport_width = viewport_height * aspect_ratio; - horizontal = viewport_width * right; - vertical = viewport_height * up; + horizontal = focus_dist * viewport_width * right; + vertical = focus_dist * viewport_height * up; - bottom_left_pixel = position - horizontal / 2.0 - vertical / 2.0 - forward; + bottom_left_pixel = position - horizontal / 2.0 - vertical / 2.0 - forward * focus_dist; } ray camera::get_ray(double u, double v) const { + vec3 rd = lens_radius * random_in_unit_disk(); + vec3 offset = rd.x * right + rd.y * up; + point3 viewport_pixel = bottom_left_pixel + u * horizontal + v * vertical; + return ray { - position, - viewport_pixel - position + position + offset, + viewport_pixel - position - offset }; } diff --git a/src/main.cpp b/src/main.cpp index 41f1280..937dc9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,52 @@ color ground_color { 1.0, 1.0, 1.0 }; color sky_color { 0.5, 0.7, 1.0 }; +hittable_list random_scene() { + hittable_list world; + + auto ground_material = std::make_shared(color{ 0.5, 0.5, 0.5 }); + world.add(std::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 = randd(); + point3 center(a + 0.9 * randd(), 0.2, b + 0.9 * randd()); + + if ((center - point3{ 4, 0.2, 0 }).length() > 0.9) { + std::shared_ptr sphere_material; + + if (choose_mat < 0.8) { + // diffuse + auto albedo = color::random() * color::random(); + sphere_material = std::make_shared(albedo); + world.add(std::make_shared(center, 0.2, sphere_material)); + } else if (choose_mat < 0.95) { + // metal + auto albedo = color::random(0.5, 1); + auto fuzz = randd(0, 0.5); + sphere_material = std::make_shared(albedo, fuzz); + world.add(std::make_shared(center, 0.2, sphere_material)); + } else { + // glass + sphere_material = std::make_shared(1.5); + world.add(std::make_shared(center, 0.2, sphere_material)); + } + } + } + } + + auto material1 = std::make_shared(1.5); + world.add(std::make_shared(point3{ 0, 1, 0 }, 1.0, material1)); + + auto material2 = std::make_shared(color{ 0.4, 0.2, 0.1 }); + world.add(std::make_shared(point3{ -4, 1, 0 }, 1.0, material2)); + + auto material3 = std::make_shared(color{ 0.7, 0.6, 0.5 }, 0.0); + world.add(std::make_shared(point3{ 4, 1, 0 }, 1.0, material3)); + + return world; +} + color ray_color(ray& r, const hittable& world, uint32_t depth) { if (depth <= 0) { return color{}; @@ -32,24 +78,17 @@ int main() { const double aspect_ratio = 16.0 / 9.0; const size_t width = 1920; const size_t height = width / aspect_ratio; - const uint32_t samples_per_pixel = 100; + const uint32_t samples_per_pixel = 1000; const uint32_t max_depth = 100; - camera camera { { -2.0, 2.0, 1.0 }, { 0.0, 0.0, -1.0 }, 20.0, aspect_ratio }; + const vec3 camera_position{ 13.0, 2.0, 3.0 }; + const vec3 camera_target{ 0.0, 0.0, 0.0 }; + const double aperture = 0.1; + const double distance_to_focus = 10; + camera camera { camera_position, camera_target, 20.0, aspect_ratio, aperture, distance_to_focus }; // World hittable objects - hittable_list world {}; - - auto material_ground = std::make_shared(color(0.8, 0.8, 0.0)); - auto material_center = std::make_shared(color(0.7, 0.3, 0.3)); - auto material_left = std::make_shared(1.5); - auto material_right = std::make_shared(color(0.8, 0.6, 0.2), 1.0); - - world.add(std::make_shared(point3( 0.0, -100.5, -1.0), 100.0, material_ground)); - world.add(std::make_shared(point3( 0.0, 0.0, -1.0), 0.5, material_center)); - world.add(std::make_shared(point3(-1.0, 0.0, -1.0), 0.5, material_left)); - world.add(std::make_shared(point3(-1.0, 0.0, -1.0), -0.49, material_left)); - world.add(std::make_shared(point3( 1.0, 0.0, -1.0), 0.5, material_right)); + hittable_list world = random_scene(); // PPM format header std::cout << "P3\n" << width << '\n' << height << "\n 255" << std::endl; diff --git a/src/vec3.cpp b/src/vec3.cpp index 3346973..94b3432 100644 --- a/src/vec3.cpp +++ b/src/vec3.cpp @@ -143,3 +143,11 @@ vec3 random_in_hemisphere(const vec3& normal) { else return -in_unit_sphere; } + +vec3 random_in_unit_disk() { + while (true) { + auto p = vec3(randd(-1, 1), randd(-1, 1), 0); + if (p.length_sq() >= 1) continue; + return p; + } +} -- cgit v1.3