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$
0

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.