45 lines
1.8 KiB
C++
45 lines
1.8 KiB
C++
#include "material.h"
|
|
|
|
#include <cmath>
|
|
|
|
bool Lambertian::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const {
|
|
//Vec3 scatter_direction = rec.normal + random_in_unit_sphere();
|
|
Vec3 scatter_direction = rec.normal + random_unit_vector();
|
|
//Vec3 scatter_direction = random_in_hemisphere(rec.normal);
|
|
scattered = Ray(rec.p, scatter_direction, r_in.time());
|
|
attenuation = albedo->value(rec.u, rec.v, rec.p);
|
|
return true;
|
|
}
|
|
|
|
bool Metal::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const {
|
|
Vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal);
|
|
scattered = Ray(rec.p, reflected + fuzz * random_in_unit_sphere(), r_in.time());
|
|
attenuation = albedo;
|
|
return (dot(scattered.direction(), rec.normal) > 0);
|
|
}
|
|
|
|
double schlick(double cosine, double ref_idx) {
|
|
auto r0 = (1 - ref_idx) / (1 + ref_idx);
|
|
r0 = r0 * r0;
|
|
return r0 + (1 - r0) * std::pow((1 - cosine), 5);
|
|
}
|
|
|
|
bool Dielectric::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const {
|
|
attenuation = Color(1.0, 1.0, 1.0);
|
|
double etai_over_etat = rec.front_face ? 1.0 / ref_idx : ref_idx;
|
|
|
|
Vec3 unit_direction = unit_vector(r_in.direction());
|
|
double cos_theta = std::fmin(dot(-unit_direction, rec.normal), 1.0);
|
|
double sin_theta = std::sqrt(1.0 - cos_theta*cos_theta);
|
|
double reflect_prob = schlick(cos_theta, etai_over_etat);
|
|
if (etai_over_etat * sin_theta > 1.0 || random_double() < reflect_prob) {
|
|
Vec3 reflected = reflect(unit_direction, rec.normal);
|
|
scattered = Ray(rec.p, reflected, r_in.time());
|
|
return true;
|
|
}
|
|
|
|
Vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat);
|
|
scattered = Ray(rec.p, refracted, r_in.time());
|
|
return true;
|
|
}
|