~ttt/ray_tracing_in_one_weekend

a546fd76a06175d9878fec8c45d984f513c72336 — Tomasz Kłak 3 years ago 86e0896
ch 10 done
3 files changed, 75 insertions(+), 8 deletions(-)

M src/main.rs
M src/material.rs
M src/vec3.rs
M src/main.rs => src/main.rs +11 -6
@@ 61,18 61,18 @@ fn main() {
    // Image
    let aspect_ratio = 16.0 / 9.0;
    let image_width = 400;
    // let image_width = 1000;
    let image_width = 1600;
    let image_width = 1000;
    // let image_width = 1600;
    let image_height = (image_width as f64 / aspect_ratio) as i32;
    let samples_per_pixel = 100;
    let samples_per_pixel = 50;
    let max_depth = 50;

    // World
    let mut world = HittableList::empty();
    let material_ground: MaterialPtr = Arc::new(Lambertian::new(Color::new(0.8, 0.8, 0.0)));
    let material_center: MaterialPtr = Arc::new(Lambertian::new(Color::new(0.7, 0.3, 0.3)));
    let material_left: MaterialPtr = Arc::new(Metal::new(Color::new(0.8, 0.8, 0.8), 0.3));
    let material_right: MaterialPtr = Arc::new(Metal::new(Color::new(0.8, 0.6, 0.2), 1.0));
    let material_center: MaterialPtr = Arc::new(Lambertian::new(Color::new(0.1, 0.2, 0.5)));
    let material_left: MaterialPtr = Arc::new(Dielectric::new(1.5));
    let material_right: MaterialPtr = Arc::new(Metal::new(Color::new(0.8, 0.6, 0.2), 0.0));

    world.add(Arc::new(Sphere::new(
        Point3::new(0.0, -100.5, -1.0),


@@ 87,6 87,11 @@ fn main() {
    world.add(Arc::new(Sphere::new(
        Point3::new(-1.0, 0.0, -1.0),
        0.5,
        material_left.clone(),
    )));
    world.add(Arc::new(Sphere::new(
        Point3::new(-1.0, 0.0, -1.0),
        -0.4,
        material_left,
    )));
    world.add(Arc::new(Sphere::new(

M src/material.rs => src/material.rs +46 -1
@@ 1,5 1,6 @@
use crate::{
    dot, random_in_unit_sphere, random_unit_vector, reflect, unit_vector, Color, HitRecord, Ray,
    dot, random_double, random_in_unit_sphere, random_unit_vector, reflect, refract, unit_vector,
    Color, HitRecord, Ray,
};
use std::fmt::Debug;



@@ 60,3 61,47 @@ impl Material for Metal {
        }
    }
}

#[derive(Debug)]
pub struct Dielectric {
    ir: f64, // Index of Refraction
}

impl Dielectric {
    pub fn new(ir: f64) -> Self {
        Self { ir }
    }

    fn reflectance(cosine: f64, ref_idx: f64) -> f64 {
        // Use Schlick's approximation for reflectance.
        let mut r0 = (1.0 - ref_idx) / (1.0 + ref_idx);
        r0 = r0 * r0;
        r0 + (1.0 - r0) * (1.0 - cosine).powi(5)
    }
}

impl Material for Dielectric {
    fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> Option<(Color, Ray)> {
        let attenuation = Color::new(1.0, 1.0, 1.0);
        let refraction_ratio = if rec.front_face {
            (1.0 / self.ir)
        } else {
            self.ir
        };

        let unit_direction = unit_vector(r_in.direction());
        let cos_theta = dot(&-unit_direction, &rec.normal).min(1.0);
        let sin_theta = (1.0 - cos_theta * cos_theta).sqrt();

        let cannot_refract = refraction_ratio * sin_theta > 1.0;
        let direction =
            if cannot_refract || Self::reflectance(cos_theta, refraction_ratio) > random_double() {
                reflect(&unit_direction, &rec.normal)
            } else {
                refract(&unit_direction, &rec.normal, refraction_ratio)
            };

        let scattered = Ray::new(&rec.p, &direction);
        Some((attenuation, scattered))
    }
}

M src/vec3.rs => src/vec3.rs +18 -1
@@ 55,7 55,17 @@ impl std::ops::Neg for &Vec3 {

    fn neg(self) -> Vec3 {
        Vec3 {
            e: [-self.e[0], -self.e[1], -self.e[1]],
            e: [-self.e[0], -self.e[1], -self.e[2]],
        }
    }
}

impl std::ops::Neg for Vec3 {
    type Output = Vec3;

    fn neg(self) -> Vec3 {
        Vec3 {
            e: [-self.e[0], -self.e[1], -self.e[2]],
        }
    }
}


@@ 228,3 238,10 @@ pub fn random_unit_vector() -> Vec3 {
pub fn reflect(v: &Vec3, n: &Vec3) -> Vec3 {
    *v - 2.0 * dot(v, n) * n
}

pub fn refract(uv: &Vec3, n: &Vec3, etai_over_etat: f64) -> Vec3 {
    let cos_theta = dot(&-uv, n).min(1.0);
    let r_out_perp = etai_over_etat * (*uv + cos_theta * n);
    let r_out_parallel = -((1.0 - r_out_perp.length_squared()).abs()).sqrt() * n;
    r_out_perp + r_out_parallel
}