add metal material

This commit is contained in:
K Tyl 2020-06-06 23:59:30 +01:00
parent b827c777e0
commit 93330c85c2
6 changed files with 109 additions and 24 deletions

View File

@ -11,9 +11,9 @@ class camera
const double FOCAL_LENGTH = 1.0; const double FOCAL_LENGTH = 1.0;
camera() : camera() :
origin_(point3(0,0,0)), origin_ (point3(0,0,0)),
horizontal_(vec3(VIEWPORT_WIDTH,0.0,0.0)), horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)),
vertical_(vec3(0.0, VIEWPORT_HEIGHT, 0.0)) vertical_ (vec3(0.0, VIEWPORT_HEIGHT, 0.0))
{ {
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH); lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH);
} }

View File

@ -1,11 +1,15 @@
#pragma once #pragma once
#include "rtweekend.h"
#include "ray.h" #include "ray.h"
class material;
struct hit_record struct hit_record
{ {
point3 p; point3 p;
vec3 normal; vec3 normal;
shared_ptr<material> mat_ptr;
double t; double t;
bool front_face; bool front_face;

View File

@ -4,6 +4,7 @@
#include "sphere.h" #include "sphere.h"
#include "colour.h" #include "colour.h"
#include "camera.h" #include "camera.h"
#include "material.h"
#include <iostream> #include <iostream>
@ -23,8 +24,15 @@ colour ray_colour(const ray& r, const hittable& world, int depth)
if (world.hit(r, 0.001, infinity, rec)) if (world.hit(r, 0.001, infinity, rec))
{ {
point3 target = rec.p + rec.normal + random_in_hemisphere(rec.normal); ray scattered;
return 0.5 * ray_colour(ray(rec.p, target - rec.p), world, depth-1); 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()); vec3 unit_direction = unit_vector(r.direction());
@ -40,18 +48,25 @@ int main()
{ {
std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n"; 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; hittable_list world;
world.add(make_shared<sphere>(point3(0,0,-1), 0.5));
world.add(make_shared<sphere>(point3(0,-100.5,-1), 100)); world.add(make_shared<sphere>(
point3(0,0,-1),
0.5,
make_shared<lambertian>(colour(0.7,0.3,0.3))));
world.add(make_shared<sphere>(
point3(0,-100.5,-1),
100,
make_shared<lambertian>(colour(0.8,0.8,0.0))));
world.add(make_shared<sphere>(
point3(1,0,-1),
0.5,
make_shared<metal>(colour(0.8,0.6,0.2))));
world.add(make_shared<sphere>(
point3(-1,0,-1),
0.5,
make_shared<metal>(colour(0.8,0.8,0.8))));
camera cam; camera cam;

56
src/material.h Normal file
View File

@ -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_;
};

View File

@ -7,15 +7,18 @@ class sphere : public hittable
{ {
public: public:
sphere() {} sphere() {}
sphere(point3 centre, double r) : sphere(point3 centre, double r, shared_ptr<material> m) :
centre_(centre), 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; virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const;
private: private:
point3 centre_; point3 centre_;
double radius_; double radius_;
shared_ptr<material> mat_ptr_;
}; };
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const 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_; vec3 outward_normal = (rec.p - centre_) / radius_;
rec.set_face_normal(r, outward_normal); rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr_;
return true; 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_; vec3 outward_normal = (rec.p - centre_) / radius_;
rec.set_face_normal(r, outward_normal); rec.set_face_normal(r, outward_normal);
rec.mat_ptr = mat_ptr_;
return true; return true;
} }

View File

@ -159,3 +159,8 @@ vec3 random_in_hemisphere(const vec3& normal)
return -in_unit_sphere; return -in_unit_sphere;
} }
} }
vec3 reflect(const vec3& v, const vec3& n)
{
return v - 2*dot(v,n)*n;
}