Add material support
This commit is contained in:
parent
6d98c22890
commit
58ffcff459
7 changed files with 112 additions and 36 deletions
16
hittable.cpp
16
hittable.cpp
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef HITTABLE_H
|
|
||||||
#define HITTABLE_H
|
|
||||||
|
|
||||||
#include "ray.h"
|
|
||||||
|
|
||||||
struct hit_record {
|
|
||||||
point3 p;
|
|
||||||
vec3 normal;
|
|
||||||
double t;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hittable {
|
|
||||||
virtual bool hit(const ray& r, double t_min, double t_max, hit_record& rec) const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
17
hittable.hpp
17
hittable.hpp
|
|
@ -1,21 +1,8 @@
|
||||||
#ifndef HITTABLE_H
|
#ifndef HITTABLE_H
|
||||||
#define HITTABLE_H
|
#define HITTABLE_H
|
||||||
|
|
||||||
#include "ray.hpp"
|
#include "rtweekend.hpp"
|
||||||
|
#include "material.hpp"
|
||||||
/* Representation of a hitpoint of a ray against a hittable object */
|
|
||||||
struct hit_record {
|
|
||||||
point3 p;
|
|
||||||
vec3 normal;
|
|
||||||
double t;
|
|
||||||
bool front_face;
|
|
||||||
|
|
||||||
inline void set_face_normal(const ray& r, const vec3& outward_normal)
|
|
||||||
{
|
|
||||||
front_face = dot(r.direction, outward_normal) < 0;
|
|
||||||
normal = front_face ? outward_normal : -outward_normal;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Virtual class that represents objects who could collide against a ray */
|
/* Virtual class that represents objects who could collide against a ray */
|
||||||
struct hittable {
|
struct hittable {
|
||||||
|
|
|
||||||
25
main.cpp
25
main.cpp
|
|
@ -21,8 +21,16 @@ color ray_color(const ray& r, const hittable& world, int32_t depth)
|
||||||
hit_record rec;
|
hit_record rec;
|
||||||
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_color(ray(rec.p, target - rec.p), world, depth-1);
|
color attenuation;
|
||||||
|
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered))
|
||||||
|
{
|
||||||
|
return attenuation * ray_color(scattered, world, depth-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return color(0,0,0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vec3 unit_direction = normalize(r.direction);
|
vec3 unit_direction = normalize(r.direction);
|
||||||
double t = 0.5 * (unit_direction.y + 1.0);
|
double t = 0.5 * (unit_direction.y + 1.0);
|
||||||
|
|
@ -64,8 +72,17 @@ int main()
|
||||||
|
|
||||||
// World
|
// World
|
||||||
hittable_list world;
|
hittable_list world;
|
||||||
world.add(std::make_shared<sphere>(point3(0,0,-1), 0.5));
|
|
||||||
world.add(std::make_shared<sphere>(point3(0,-100.5,-1), 100));
|
std::shared_ptr<lambertian> material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
|
||||||
|
std::shared_ptr<lambertian> material_center = make_shared<lambertian>(color(0.7, 0.3, 0.3));
|
||||||
|
std::shared_ptr<metal> material_left = make_shared<metal>(color(0.8, 0.8, 0.8));
|
||||||
|
std::shared_ptr<metal> material_right = make_shared<metal>(color(0.8, 0.6, 0.2));
|
||||||
|
|
||||||
|
world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
|
||||||
|
world.add(make_shared<sphere>(point3( 0.0, 0.0, -1.0), 0.5, material_center));
|
||||||
|
world.add(make_shared<sphere>(point3(-1.0, 0.0, -1.0), 0.5, material_left));
|
||||||
|
world.add(make_shared<sphere>(point3( 1.0, 0.0, -1.0), 0.5, material_right));
|
||||||
|
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
camera cam;
|
camera cam;
|
||||||
|
|
|
||||||
52
material.hpp
Normal file
52
material.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef MATERIAL_H
|
||||||
|
#define MATERIAL_H
|
||||||
|
|
||||||
|
#include "rtweekend.hpp"
|
||||||
|
|
||||||
|
struct material {
|
||||||
|
virtual bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct lambertian : material {
|
||||||
|
/* Attributes */
|
||||||
|
color albedo;
|
||||||
|
// Constructor
|
||||||
|
lambertian(const color& c) { albedo = c; }
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
virtual bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override
|
||||||
|
{
|
||||||
|
vec3 scatter_direction = rec.normal + random_unit_vector();
|
||||||
|
|
||||||
|
/* NOTE: it is possible that the random vector we generate is exactly opposite to the normal vector,
|
||||||
|
in which case it will sum to a near-zero scatter vector and generate degenerate results.
|
||||||
|
We check for near-zero vectors here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (scatter_direction.near_zero())
|
||||||
|
scatter_direction = rec.normal;
|
||||||
|
|
||||||
|
scattered = ray(rec.p, scatter_direction);
|
||||||
|
attenuation = albedo;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
};
|
||||||
|
|
||||||
|
struct metal : material {
|
||||||
|
/* Attributes */
|
||||||
|
color albedo;
|
||||||
|
// Constructor
|
||||||
|
metal(const color& c) { albedo = c; };
|
||||||
|
|
||||||
|
virtual bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override
|
||||||
|
{
|
||||||
|
vec3 reflected = reflect(normalize(r_in.direction), rec.normal);
|
||||||
|
scattered = ray(rec.p, reflected);
|
||||||
|
attenuation = albedo;
|
||||||
|
return (dot(scattered.direction, rec.normal) > 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -33,5 +33,25 @@ inline double clamp(double v, double min, double max)
|
||||||
#include "ray.hpp"
|
#include "ray.hpp"
|
||||||
#include "vec3.hpp"
|
#include "vec3.hpp"
|
||||||
|
|
||||||
|
struct material;
|
||||||
|
|
||||||
|
/* Common data structures */
|
||||||
|
|
||||||
|
struct hit_record {
|
||||||
|
point3 p;
|
||||||
|
vec3 normal;
|
||||||
|
std::shared_ptr<material> mat_ptr;
|
||||||
|
double t;
|
||||||
|
bool front_face;
|
||||||
|
|
||||||
|
inline void set_face_normal(const ray& r, const vec3& outward_normal)
|
||||||
|
{
|
||||||
|
front_face = dot(r.direction, outward_normal) < 0;
|
||||||
|
normal = front_face ? outward_normal : -outward_normal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ struct sphere : hittable {
|
||||||
/* Attributes */
|
/* Attributes */
|
||||||
point3 center;
|
point3 center;
|
||||||
double radius;
|
double radius;
|
||||||
|
std::shared_ptr<material> mat_ptr;
|
||||||
|
|
||||||
/* Contructor */
|
/* Contructor */
|
||||||
sphere(point3 c, double r)
|
sphere(point3 c, double r, std::shared_ptr<material> m)
|
||||||
{
|
{
|
||||||
center = c;
|
center = c;
|
||||||
radius = r;
|
radius = r;
|
||||||
|
mat_ptr = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Virtual methods declaration */
|
/* Virtual methods declaration */
|
||||||
|
|
@ -46,6 +48,7 @@ bool sphere::hit(const ray& r, double t_min, double t_max, hit_record& rec) cons
|
||||||
rec.p = r.at(rec.t);
|
rec.p = r.at(rec.t);
|
||||||
vec3 outward_normal = (rec.p - center) / radius;
|
vec3 outward_normal = (rec.p - center) / radius;
|
||||||
rec.set_face_normal(r, outward_normal);
|
rec.set_face_normal(r, outward_normal);
|
||||||
|
rec.mat_ptr = mat_ptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
vec3.hpp
13
vec3.hpp
|
|
@ -76,6 +76,13 @@ struct vec3 {
|
||||||
{
|
{
|
||||||
return vec3(random_double(min, max), random_double(min, max), random_double(min, max));
|
return vec3(random_double(min, max), random_double(min, max), random_double(min, max));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if all vector components are near zero
|
||||||
|
bool near_zero() const
|
||||||
|
{
|
||||||
|
double s = 1e-8;
|
||||||
|
return (fabs(x) < s) && (fabs(y) < s) && (fabs(z) < s);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Type aliases */
|
/* Type aliases */
|
||||||
|
|
@ -175,4 +182,10 @@ vec3 random_in_hemisphere(const vec3& normal)
|
||||||
return -in_unit_sphere;
|
return -in_unit_sphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reflect like a metallic material
|
||||||
|
vec3 reflect(const vec3& v, const vec3 n)
|
||||||
|
{
|
||||||
|
return v - 2*dot(v,n)*n;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue