add glass

This commit is contained in:
K Tyl 2020-06-07 01:13:39 +01:00
parent 93330c85c2
commit ac6cc84bf5
3 changed files with 72 additions and 6 deletions

View File

@ -39,7 +39,7 @@ colour ray_colour(const ray& r, const hittable& world, int depth)
auto t = 0.5 * (unit_direction.y() + 1.0); auto t = 0.5 * (unit_direction.y() + 1.0);
auto a = colour(0.5, 0.6, 0.7); auto a = colour(0.5, 0.6, 0.7);
auto b = colour(1.0, 1.0, 1.0); auto b = colour(0.5, 0.5, 0.5);
return lerp(a, b, t); return lerp(a, b, t);
} }
@ -53,7 +53,7 @@ int main()
world.add(make_shared<sphere>( world.add(make_shared<sphere>(
point3(0,0,-1), point3(0,0,-1),
0.5, 0.5,
make_shared<lambertian>(colour(0.7,0.3,0.3)))); make_shared<lambertian>(colour(0.1,0.2,0.5))));
world.add(make_shared<sphere>( world.add(make_shared<sphere>(
point3(0,-100.5,-1), point3(0,-100.5,-1),
100, 100,
@ -62,11 +62,15 @@ int main()
world.add(make_shared<sphere>( world.add(make_shared<sphere>(
point3(1,0,-1), point3(1,0,-1),
0.5, 0.5,
make_shared<metal>(colour(0.8,0.6,0.2)))); make_shared<metal>(colour(0.8,0.6,0.2), 0.0)));
world.add(make_shared<sphere>( world.add(make_shared<sphere>(
point3(-1,0,-1), point3(-1,0,-1),
0.5, 0.5,
make_shared<metal>(colour(0.8,0.8,0.8)))); make_shared<dielectric>(1.5)));
world.add(make_shared<sphere>(
point3(-1,0,-1),
-0.45,
make_shared<dielectric>(1.5)));
camera cam; camera cam;

View File

@ -13,6 +13,13 @@ class material
ray& scattered) const = 0; ray& scattered) const = 0;
}; };
double schlick(double cosine, double refraction_index)
{
auto r0 = (1-refraction_index) / (1+refraction_index);
r0 = r0*r0;
return r0 + (1-r0)*pow(1-cosine, 5);
}
class lambertian : public material class lambertian : public material
{ {
public: public:
@ -37,7 +44,9 @@ class lambertian : public material
class metal : public material class metal : public material
{ {
public: public:
metal(const colour& a) : albedo_(a) {} metal(const colour& a, double f) :
albedo_(a),
fuzz_(f < 1 ? f : 1) {}
virtual bool scatter( virtual bool scatter(
const ray& r_in, const ray& r_in,
@ -46,11 +55,55 @@ class metal : public material
ray& scattered) const ray& scattered) const
{ {
vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal);
scattered = ray(rec.p, reflected); scattered = ray(rec.p, reflected + fuzz_*random_in_unit_sphere());
attenuation = albedo_; attenuation = albedo_;
return dot(scattered.direction(), rec.normal) > 0; return dot(scattered.direction(), rec.normal) > 0;
} }
private: private:
colour albedo_; colour albedo_;
double fuzz_;
};
class dielectric : public material
{
public:
dielectric(double ri) : refraction_index_(ri) {}
virtual bool scatter(
const ray& r_in,
const hit_record& rec,
colour& attenuation,
ray& scattered) const
{
attenuation = colour(1.0,1.0,1.0);
double etai_over_etat = rec.front_face ? (1.0 / refraction_index_) : refraction_index_;
vec3 unit_direction = unit_vector(r_in.direction());
double cos_theta = fmin(dot(-unit_direction, rec.normal), 1.0);
double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
if (etai_over_etat * sin_theta > 1.0)
{
vec3 reflected = reflect(unit_direction, rec.normal);
scattered = ray(rec.p, reflected);
return true;
}
double reflect_prob = schlick(cos_theta, etai_over_etat);
if (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;
}
private:
double refraction_index_;
}; };

View File

@ -164,3 +164,12 @@ vec3 reflect(const vec3& v, const vec3& n)
{ {
return v - 2*dot(v,n)*n; return v - 2*dot(v,n)*n;
} }
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 = -sqrt(1.0 - r_out_parallel.length_squared()) * n;
return r_out_parallel + r_out_perp;
}