Adding glass
This commit is contained in:
		| @ -29,14 +29,55 @@ class lambertian : public material{ | |||||||
|  |  | ||||||
| class metal : public material{ | class metal : public material{ | ||||||
|     public: |     public: | ||||||
|         metal(const color& a) : albedo(a){} |         metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1){} | ||||||
|  |  | ||||||
|         virtual bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)const override { |         virtual 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); |             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); | ||||||
|         } |         } | ||||||
|     public: |     public: | ||||||
|         color albedo; |         color albedo; | ||||||
|  |         double fuzz; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class dielectric : public material{ | ||||||
|  |     public: | ||||||
|  |         dielectric(double index_of_refraction) : ir(index_of_refraction){} | ||||||
|  |  | ||||||
|  |         virtual bool scatter (const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered) const override{ | ||||||
|  |             attenuation = color(1.0,1.0,1.0); | ||||||
|  |             double refraction_ratio = rec.front_face ? (1.0/ir) : ir; | ||||||
|  |  | ||||||
|  |             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); | ||||||
|  |             bool cannot_refract = refraction_ratio * sin_theta > 1.0; | ||||||
|  |             vec3 direction; | ||||||
|  |  | ||||||
|  |             if(cannot_refract || reflectance(cos_theta, refraction_ratio) > random_double()){ | ||||||
|  |                 // Must reflect | ||||||
|  |                 direction = reflect(unit_direction, rec.normal); | ||||||
|  |             } else { | ||||||
|  |                 // can refract  | ||||||
|  |                 direction = refract(unit_direction, rec.normal, refraction_ratio); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             scattered = ray(rec.p, direction); | ||||||
|  |  | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         double ir; | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         static double reflectance(double cosine, double ref_idx){ | ||||||
|  |             // use Schlik's approximation | ||||||
|  |             auto r0 = (1-ref_idx) / (1+ref_idx); | ||||||
|  |             r0 = r0*r0; | ||||||
|  |             return r0 + (1-r0)*pow((1-cosine), 5);    | ||||||
|  |         } | ||||||
| }; | }; | ||||||
| @ -41,14 +41,15 @@ int main () | |||||||
|     hittable_list world; |     hittable_list world; | ||||||
|  |  | ||||||
|     auto material_ground = make_shared<lambertian>(color(0.8,0.8, 0.0)); |     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_center = make_shared<lambertian>(color(0.1, 0.2, 0.5)); | ||||||
|     auto material_left = make_shared<metal> (color(0.8,0.8,0.8)); |     auto material_left = make_shared<dielectric> (1.5); | ||||||
|     auto material_right = make_shared<metal>(color(0.8,0.6,0.2)); |     auto material_right = make_shared<metal>(color(0.8,0.6,0.2), 0.0); | ||||||
|      |      | ||||||
|  |  | ||||||
|     world.add(make_shared<sphere>(point3(0,-100.5,-1), 100.0, material_ground)); |     world.add(make_shared<sphere>(point3(0,-100.5,-1), 100.0, material_ground)); | ||||||
|     world.add(make_shared<sphere>(point3(0,0,-1), 0.5,  material_center)); |     world.add(make_shared<sphere>(point3(0,0,-1), 0.5,  material_center)); | ||||||
|     world.add(make_shared<sphere>(point3(-1.0, 0.0, -1), 0.5, material_left)); |     world.add(make_shared<sphere>(point3(-1.0, 0.0, -1), 0.5, material_left)); | ||||||
|  |     world.add(make_shared<sphere>(point3(-1.0, 0.0, -1), -0.4, material_left)); | ||||||
|     world.add(make_shared<sphere>(point3(1.0, 0.0, -1), 0.5, material_right)); |     world.add(make_shared<sphere>(point3(1.0, 0.0, -1), 0.5, material_right)); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -130,4 +130,11 @@ vec3 random_in_hemisphere (const vec3& normal){ | |||||||
|  |  | ||||||
| vec3 reflect (const vec3& v, const vec3& n){ | 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 = fmin(dot(-uv,n), 1.0); | ||||||
|  |     vec3 r_out_perp = etai_over_etat * (uv + cos_theta*n); | ||||||
|  |     vec3 r_out_parallel = -sqrt(fabs(1.0 - r_out_perp.length_squared())) * n; | ||||||
|  |     return r_out_perp + r_out_parallel;  | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user