aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2020-12-22 23:19:59 +0100
committerladevieq <ladevie.quentin@gmail.com>2020-12-22 23:19:59 +0100
commit3b567beadb6275adf4b60e1eca003e44014c3786 (patch)
tree7e5c65c19ddee300c01ad2ef698b66ebf9a4802e
parent6b6ef77808585713ab1d04f03e970865b7e7ddb8 (diff)
Defocus blur & randow scene generation
-rw-r--r--include/camera.hpp14
-rw-r--r--include/vec3.hpp2
-rw-r--r--src/camera.cpp30
-rw-r--r--src/main.cpp67
-rw-r--r--src/vec3.cpp8
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<lambertian>(color{ 0.5, 0.5, 0.5 });
+ world.add(std::make_shared<sphere>(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<material> sphere_material;
+
+ if (choose_mat < 0.8) {
+ // diffuse
+ auto albedo = color::random() * color::random();
+ sphere_material = std::make_shared<lambertian>(albedo);
+ world.add(std::make_shared<sphere>(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<metal>(albedo, fuzz);
+ world.add(std::make_shared<sphere>(center, 0.2, sphere_material));
+ } else {
+ // glass
+ sphere_material = std::make_shared<dielectric>(1.5);
+ world.add(std::make_shared<sphere>(center, 0.2, sphere_material));
+ }
+ }
+ }
+ }
+
+ auto material1 = std::make_shared<dielectric>(1.5);
+ world.add(std::make_shared<sphere>(point3{ 0, 1, 0 }, 1.0, material1));
+
+ auto material2 = std::make_shared<lambertian>(color{ 0.4, 0.2, 0.1 });
+ world.add(std::make_shared<sphere>(point3{ -4, 1, 0 }, 1.0, material2));
+
+ auto material3 = std::make_shared<metal>(color{ 0.7, 0.6, 0.5 }, 0.0);
+ world.add(std::make_shared<sphere>(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<lambertian>(color(0.8, 0.8, 0.0));
- auto material_center = std::make_shared<lambertian>(color(0.7, 0.3, 0.3));
- auto material_left = std::make_shared<dielectric>(1.5);
- auto material_right = std::make_shared<metal>(color(0.8, 0.6, 0.2), 1.0);
-
- world.add(std::make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
- world.add(std::make_shared<sphere>(point3( 0.0, 0.0, -1.0), 0.5, material_center));
- world.add(std::make_shared<sphere>(point3(-1.0, 0.0, -1.0), 0.5, material_left));
- world.add(std::make_shared<sphere>(point3(-1.0, 0.0, -1.0), -0.49, material_left));
- world.add(std::make_shared<sphere>(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;
+ }
+}