1
$\begingroup$

I am interested in Path Tracing, I currently follow the Ray Tracing in a weekend book. When implementing the metal material, I get a strange artifact on the edge of the sphere that does not appear in the book's result. I might be caused by the fuzz parameter, when it's set to zero, it does not occur.

I wrote my code in Rust

Screenshots:
Fuzziness set to 0.0
Fuzziness set to 0.0

Fuzziness set to 0.5
Fuzziness set to 0.5

As you can see there is a white outline-like artifact at the edge of the sphere.
I am not sure what causes that...

The full code is available here: https://github.com/AregevDev/pathtracer
Some highlights:

My random point function

fn random_double() -> f64 {
    let mut rnd = rand::thread_rng();
    rnd.gen::<f64>()
}

// Generate a random point in the unit sphere
fn random_in_unit_sphere() -> Vector3 {
    loop {
        let p =
            2.0 * Vector3::new(
                random_double() as f32,
                random_double() as f32,
                random_double() as f32,
            ) - Vector3::new(1.0, 1.0, 1.0);
        if p.squared_length() <= 1.0 {
            return p;
        }
    }
}

My material scatter function, I match the material type and calculate the rays accordingly:

pub fn scatter(&self, ray_in: Ray, record: &HitRecord) -> Option<Scatter> {
        match *self {
            Material::Lambertian { albedo } => {
                let mut scattered = Scatter::default();
                let target = record.p + record.normal + random_in_unit_sphere();

                scattered.color = albedo;
                scattered.ray = Some(Ray::new(record.p, target - record.p));

                Some(scattered)
            }
            Material::Metal { albedo, fuzz } => {
                let mut scattered = Scatter::default();
                let reflected = ray_in.direction.normalize().reflect(record.normal);
                let new_fuzz = fuzz.min(1.0);

                scattered.color = albedo;
                scattered.ray = Some(Ray::new(
                    record.p,
                    reflected + new_fuzz * random_in_unit_sphere(),
                ));

                if scattered.ray.unwrap().direction.dot(record.normal) > 0.0 {
                    Some(scattered)
                } else {
                    None
                }
            }
            _ => None,
        }
    }

Thanks

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.