From 93330c85c2ebfcb27295bfd92e7817ccec41c624 Mon Sep 17 00:00:00 2001 From: K Tyl Date: Sat, 6 Jun 2020 23:59:30 +0100 Subject: [PATCH] add metal material --- src/camera.h | 6 +++--- src/hittable.h | 12 +++++++---- src/main.cpp | 41 ++++++++++++++++++++++++------------ src/material.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/sphere.h | 13 ++++++++---- src/vec3.h | 5 +++++ 6 files changed, 109 insertions(+), 24 deletions(-) create mode 100644 src/material.h diff --git a/src/camera.h b/src/camera.h index 18b3e4d..85bc568 100644 --- a/src/camera.h +++ b/src/camera.h @@ -11,9 +11,9 @@ class camera 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)) + origin_ (point3(0,0,0)), + horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)), + vertical_ (vec3(0.0, VIEWPORT_HEIGHT, 0.0)) { lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH); } diff --git a/src/hittable.h b/src/hittable.h index f8e050a..c350b32 100644 --- a/src/hittable.h +++ b/src/hittable.h @@ -1,13 +1,17 @@ #pragma once +#include "rtweekend.h" #include "ray.h" +class material; + struct hit_record { - point3 p; - vec3 normal; - double t; - bool front_face; + point3 p; + vec3 normal; + shared_ptr mat_ptr; + double t; + bool front_face; inline void set_face_normal(const ray& r, const vec3& outward_normal) { diff --git a/src/main.cpp b/src/main.cpp index c3aa001..32355f9 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "sphere.h" #include "colour.h" #include "camera.h" +#include "material.h" #include @@ -23,8 +24,15 @@ colour ray_colour(const ray& r, const hittable& world, int depth) if (world.hit(r, 0.001, infinity, rec)) { - point3 target = rec.p + rec.normal + random_in_hemisphere(rec.normal); - return 0.5 * ray_colour(ray(rec.p, target - rec.p), world, depth-1); + ray scattered; + colour attenuation; + + if (rec.mat_ptr->scatter(r, rec, attenuation, scattered)) + { + return attenuation * ray_colour(scattered, world, depth-1); + } + + return colour(0,0,0); } vec3 unit_direction = unit_vector(r.direction()); @@ -40,18 +48,25 @@ int main() { std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; - auto viewport_height = 2.0; - auto viewport_width = ASPECT_RATIO * viewport_height; - auto focal_length = 1.0; - - auto origin = point3(0, 0, 0); - auto horizontal = vec3(viewport_width, 0, 0); - auto vertical = vec3(0, viewport_height, 0); - auto lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0,0,focal_length); - hittable_list world; - world.add(make_shared(point3(0,0,-1), 0.5)); - world.add(make_shared(point3(0,-100.5,-1), 100)); + + world.add(make_shared( + point3(0,0,-1), + 0.5, + make_shared(colour(0.7,0.3,0.3)))); + world.add(make_shared( + point3(0,-100.5,-1), + 100, + make_shared(colour(0.8,0.8,0.0)))); + + world.add(make_shared( + point3(1,0,-1), + 0.5, + make_shared(colour(0.8,0.6,0.2)))); + world.add(make_shared( + point3(-1,0,-1), + 0.5, + make_shared(colour(0.8,0.8,0.8)))); camera cam; diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..cd79906 --- /dev/null +++ b/src/material.h @@ -0,0 +1,56 @@ +#pragma once + +#include "rtweekend.h" +#include "hittable.h" + +class material +{ + public: + virtual bool scatter( + const ray& r_in, + const hit_record& rec, + colour& attenuation, + ray& scattered) const = 0; +}; + +class lambertian : public material +{ + public: + lambertian(const colour& a) : albedo_(a) {} + + virtual bool scatter( + const ray& r_in, + const hit_record& rec, + colour& attenuation, + ray& scattered) const + { + vec3 scatter_direction = rec.normal + random_unit_vector(); + scattered = ray(rec.p, scatter_direction); + attenuation = albedo_; + return true; + } + + private: + colour albedo_; +}; + +class metal : public material +{ + public: + metal(const colour& a) : albedo_(a) {} + + virtual bool scatter( + const ray& r_in, + const hit_record& rec, + colour& attenuation, + ray& scattered) const + { + vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); + scattered = ray(rec.p, reflected); + attenuation = albedo_; + return dot(scattered.direction(), rec.normal) > 0; + } + + private: + colour albedo_; +}; diff --git a/src/sphere.h b/src/sphere.h index cb3e521..91c01f5 100644 --- a/src/sphere.h +++ b/src/sphere.h @@ -7,15 +7,18 @@ class sphere : public hittable { public: sphere() {} - sphere(point3 centre, double r) : + sphere(point3 centre, double r, shared_ptr m) : centre_(centre), - radius_(r) {}; + radius_(r), + mat_ptr_(m) + {}; virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const; private: - point3 centre_; - double radius_; + point3 centre_; + double radius_; + shared_ptr mat_ptr_; }; bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const @@ -38,6 +41,7 @@ bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) cons vec3 outward_normal = (rec.p - centre_) / radius_; rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr_; return true; } @@ -50,6 +54,7 @@ bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) cons vec3 outward_normal = (rec.p - centre_) / radius_; rec.set_face_normal(r, outward_normal); + rec.mat_ptr = mat_ptr_; return true; } diff --git a/src/vec3.h b/src/vec3.h index b2abc05..ff09f68 100755 --- a/src/vec3.h +++ b/src/vec3.h @@ -159,3 +159,8 @@ vec3 random_in_hemisphere(const vec3& normal) return -in_unit_sphere; } } + +vec3 reflect(const vec3& v, const vec3& n) +{ + return v - 2*dot(v,n)*n; +}