Adding dielectric material.

This commit is contained in:
Faerbit 2020-06-07 00:03:25 +02:00
parent 129854222d
commit 3683a309c5
6 changed files with 52 additions and 6 deletions

View File

@ -9,7 +9,7 @@ TARGET = wtracer
all: $(TARGET) run
run:
run: $(TARGET)
time -f '%E elapsed' ./wtracer > image.ppm
eog image.ppm

View File

@ -1,5 +1,7 @@
#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();
@ -15,3 +17,28 @@ bool Metal::scatter(const Ray& r_in, const hit_record& rec, Color& attenuation,
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);
return true;
}
Vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat);
scattered = Ray(rec.p, refracted);
return true;
}

View File

@ -31,4 +31,14 @@ private:
double fuzz;
};
double schlick(double cosine, double ref_idx);
class Dielectric : public Material {
public:
Dielectric(double ri) : ref_idx(ri) {}
virtual bool scatter(const Ray& r_in, const hit_record& rec, Color& attenuation, Ray& scattered) const;
private:
double ref_idx;
};
#endif // MATERIAL_H

View File

@ -22,3 +22,10 @@ Vec3 random_in_hemisphere(const Vec3& normal) {
else
return -in_unit_sphere;
}
Vec3 refract(const Vec3& uv, const Vec3& n, double etai_over_etat) {
auto cos_theta = dot(-uv, n);
Vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n);
Vec3 r_out_perp = - std::sqrt(1.0 - r_out_parallel.length_squared()) * n;
return r_out_parallel + r_out_perp;
}

2
vec3.h
View File

@ -122,4 +122,6 @@ Vec3 random_unit_vector();
Vec3 random_in_hemisphere(const Vec3& normal);
Vec3 refract(const Vec3& uv, const Vec3& n, double etai_over_etat);
#endif // VEC3_H

View File

@ -41,14 +41,14 @@ int main() {
std::cout << "P3\n" << image_width << " " << image_height << "\n255\n";
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));*/
world.add(std::make_shared<Sphere>(Point3(0, 0, -1), 0.5, std::make_shared<Lambertian>(Color(0.7, 0.3, 0.3))));
world.add(std::make_shared<Sphere>(Point3(0, 0, -1), 0.5, std::make_shared<Lambertian>(Color(0.1, 0.2, 0.5))));
world.add(std::make_shared<Sphere>(Point3(0, -100.5, -1), 100, std::make_shared<Lambertian>(Color(0.8, 0.8, 0.0))));
world.add(std::make_shared<Sphere>(Point3(1, 0, -1), 0.5, std::make_shared<Metal>(Color(0.8, 0.6, 0.2), 0.3)));
world.add(std::make_shared<Sphere>(Point3(-1, 0, -1), 0.5, std::make_shared<Metal>(Color(0.8, 0.8, 0.8), 1.0)));
world.add(std::make_shared<Sphere>(Point3(1, 0, -1), 0.5, std::make_shared<Metal>(Color(0.8, 0.6, 0.2), 0.0)));
world.add(std::make_shared<Sphere>(Point3(-1, 0, -1), 0.5, std::make_shared<Dielectric>(1.45)));
Camera cam;