feat: add metal metarial
This commit is contained in:
parent
cd414d1aeb
commit
14ac9f2ec0
1
color.h
1
color.h
@ -2,6 +2,7 @@
|
||||
#define COLOR_H
|
||||
|
||||
#include "rtweekend.h"
|
||||
#include "vec3.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -1,11 +1,15 @@
|
||||
#ifndef HITTABLE_H
|
||||
#define HITTABLE_H
|
||||
|
||||
#include "rtweekend.h"
|
||||
#include "ray.h"
|
||||
|
||||
class material;
|
||||
|
||||
struct hit_record {
|
||||
point3 p;
|
||||
vec3 normal;
|
||||
shared_ptr<material> mat_ptr;
|
||||
double t;
|
||||
bool front_face;
|
||||
|
||||
|
22
main.cc
22
main.cc
@ -1,9 +1,10 @@
|
||||
#include "rtweekend.h"
|
||||
|
||||
#include "color.h"
|
||||
#include "rtweekend.h"
|
||||
#include "hittable_list.h"
|
||||
#include "sphere.h"
|
||||
#include "camera.h"
|
||||
#include "material.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -15,8 +16,11 @@ color ray_color(const ray& r, const hittable& world, int depth) {
|
||||
return color(0, 0, 0);
|
||||
|
||||
if (world.hit(r, 0.001, infinity, rec)) {
|
||||
point3 target = rec.p + rec.normal + random_in_hemisphere(rec.normal);
|
||||
return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1);
|
||||
ray scattered;
|
||||
color attenuation;
|
||||
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered))
|
||||
return attenuation * ray_color(scattered, world, depth-1);
|
||||
return color(0,0,0);
|
||||
}
|
||||
|
||||
vec3 unit_direction = unit_vector(r.direction());
|
||||
@ -34,8 +38,16 @@ int main() {
|
||||
|
||||
// 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));
|
||||
|
||||
auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
|
||||
auto material_center = make_shared<lambertian>(color(0.7, 0.3, 0.3));
|
||||
auto material_left = make_shared<metal>(color(0.8, 0.8, 0.8), 0.3);
|
||||
auto material_right = make_shared<metal>(color(0.8, 0.6, 0.2), 1.0);
|
||||
|
||||
world.add(make_shared<sphere>(point3(0, -100.5, -1), 100, material_ground));
|
||||
world.add(make_shared<sphere>(point3(0, 0, -1), 0.5, material_center));
|
||||
world.add(make_shared<sphere>(point3(-1, 0, -1), 0.5, material_left));
|
||||
world.add(make_shared<sphere>(point3(1, 0, -1), 0.5, material_right));
|
||||
|
||||
// Camera
|
||||
camera cam;
|
||||
|
56
material.h
Normal file
56
material.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef MATERIAL_H
|
||||
#define MATERIAL_H
|
||||
|
||||
#include "hittable.h"
|
||||
#include "rtweekend.h"
|
||||
#include "vec3.h"
|
||||
|
||||
struct hit_record;
|
||||
|
||||
class material {
|
||||
public:
|
||||
virtual bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class lambertian : public material {
|
||||
public:
|
||||
lambertian(const color& a) : albedo(a) {}
|
||||
|
||||
bool scatter(
|
||||
const ray &r_in, const hit_record &rec, color &attenuation, ray &scattered
|
||||
) const override {
|
||||
auto scatter_direction = rec.normal + random_in_hemisphere(rec.normal);
|
||||
|
||||
// Catch degenerate scatter direction
|
||||
if (scatter_direction.near_zero())
|
||||
scatter_direction = rec.normal;
|
||||
|
||||
scattered = ray(rec.p, scatter_direction);
|
||||
attenuation = albedo;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
color albedo;
|
||||
};
|
||||
|
||||
class metal : public material {
|
||||
public:
|
||||
metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {}
|
||||
|
||||
bool scatter(
|
||||
const ray &r_in, const hit_record &rec, color &attenuation, ray &scattered
|
||||
) const override {
|
||||
vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal);
|
||||
scattered = ray(rec.p, reflected + fuzz*random_in_hemisphere(rec.normal));
|
||||
attenuation = albedo;
|
||||
return (dot(scattered.direction(), rec.normal) > 0);
|
||||
}
|
||||
|
||||
public:
|
||||
color albedo;
|
||||
double fuzz;
|
||||
};
|
||||
|
||||
#endif
|
@ -36,8 +36,4 @@ inline double random_double(double min, double max) {
|
||||
return min + (max - min) * random_double();
|
||||
}
|
||||
|
||||
// Common headers
|
||||
#include "ray.h"
|
||||
#include "vec3.h"
|
||||
|
||||
#endif
|
||||
|
4
sphere.h
4
sphere.h
@ -7,7 +7,7 @@
|
||||
class sphere : public hittable {
|
||||
public:
|
||||
sphere() {}
|
||||
sphere(point3 cen, double r) : center(cen), radius(r) {};
|
||||
sphere(point3 cen, double r, shared_ptr<material> m) : center(cen), radius(r), mat_ptr(m) {};
|
||||
|
||||
virtual bool hit(
|
||||
const ray& r, double t_min, double t_max, hit_record& rec) const override;
|
||||
@ -15,6 +15,7 @@ class sphere : public hittable {
|
||||
public:
|
||||
point3 center;
|
||||
double radius;
|
||||
shared_ptr<material> mat_ptr;
|
||||
};
|
||||
|
||||
bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) const {
|
||||
@ -39,6 +40,7 @@ bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) cons
|
||||
rec.p = r.at(rec.t);
|
||||
vec3 outward_normal = (rec.p - center) / radius;
|
||||
rec.set_face_normal(r, outward_normal);
|
||||
rec.mat_ptr = mat_ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
12
vec3.h
12
vec3.h
@ -1,10 +1,11 @@
|
||||
#ifndef VEC3_H
|
||||
#define VEC3_H
|
||||
|
||||
#include "rtweekend.h"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "rtweekend.h"
|
||||
|
||||
using std::sqrt;
|
||||
|
||||
class vec3 {
|
||||
@ -54,6 +55,11 @@ class vec3 {
|
||||
return vec3(random_double(min, max), random_double(min, max), random_double(min, max));
|
||||
}
|
||||
|
||||
bool near_zero() const {
|
||||
auto s = 1e-8;
|
||||
return fabs(e[0]) < s && fabs(e[1]) < s && fabs(e[2]) < s;
|
||||
}
|
||||
|
||||
public:
|
||||
double e[3];
|
||||
};
|
||||
@ -128,4 +134,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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user