fn trace_ray(ray: &Ray, spheres: &Vec<Sphere>, lights: &Vec<Light>, depth: u32) -> Vector3<f32> {
    let mut closest_match = f32::MAX;
    let mut closest_sphere: Option<&Sphere> = None;

    if depth >= MAX_DEPTH {
        return infinite_color(&ray);
    }
    // find the closest intersection, if any
    for sphere in spheres {
        match sphere.intersect(&ray) {
            None => {}
            Some(Intersection { distance }) => {
                if distance < closest_match {
                    closest_match = distance;
                    closest_sphere = Some(&sphere);
                }
            }
        }
    }

    match closest_sphere {
        Some(sphere) => {
            // Compute an intersection point. Doing this here avoids unnecessary alloctions.
            let intersection_point = ray.origin + ray.direction * closest_match;
            match sphere.surface {
                // Diffuse surface
                // Find all unoccluded light sources and add up their light contributions.
                Surface::Diffuse { color } => {
                    let mut light_intensity: f32 = 0.0;
                    for light in lights {
                        // Use a shadow ray to check whether a light source is visible:
                        // If the ray between the intersection point and a light source does not
                        // intersect other scene object before the light source, the light source is
                        // unoccluded.
                        let shadow_ray = Ray::from_to(intersection_point, &light.coordinates);
                        let light_distance = (light.coordinates - intersection_point).norm();
                        let mut occluded = false;
                        for other_sphere in spheres {
                            if other_sphere as *const _ != sphere as *const _ {
                                if let Some(distance) = other_sphere.intersect(&shadow_ray) {
                                    if distance.distance < light_distance {
                                        occluded = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if occluded {
                            continue;
                        }
                        let surface_normal = sphere.surface_normal(&intersection_point);
                        let light_intensity_scaling_factor =
                            surface_normal.dot(&shadow_ray.direction);
                        if light_intensity_scaling_factor > 0.0 {
                            light_intensity += light.intensity * light_intensity_scaling_factor;
                        }
                    }
                    color * light_intensity
                }
                // Specular surface: Recurse using a reflected ray.
                Surface::Specular => {
                    let surface_normal = sphere.surface_normal(&intersection_point);
                    let to_source = -ray.direction;
                    let out_direction =
                        2.0 * to_source.dot(&surface_normal) * surface_normal - to_source;
                    trace_ray(
                        &Ray::origin_direction(intersection_point, out_direction),
                        spheres,
                        lights,
                        depth + 1,
                    )
                }
            }
        }
        // no intersection, return color at infinity
        None => infinite_color(&ray),
    }
}
/// Recursive function to compute the color to draw for a given ray and a given scenery,
/// at recursion depth `depth`.
///
/// If `depth` is greater than or equal to `MAX_DEPTH`, we return the color at infinity.
Recursive function to compute the color to draw for a given ray and a given scenery,
at recursion depth `depth`.

If `depth` is greater than or equal to `MAX_DEPTH`, we return the color at infinity.
Recursive function to compute the color to draw for a given ray and a given scenery at recursion depth ` depth ` . If ` depth ` is greater than or equal to ` MAX_DEPTH ` we return the color at infinity .
fn trace_ray(ray: &Ray, spheres: &Vec<Sphere>, lights: &Vec<Light>, depth: u32) -> Vector3<f32> {
    let mut closest_match = f32::MAX;
    let mut closest_sphere: Option<&Sphere> = None;
    if depth >= MAX_DEPTH {
        return infinite_color(&ray);
    }
    // find the closest intersection, if any
    for sphere in spheres {
        match sphere.intersect(&ray) {
            None => {}
            Some(Intersection { distance }) => {
                if distance < closest_match {
                    closest_match = distance;
                    closest_sphere = Some(&sphere);
                }
            }
        }
    }
    match closest_sphere {
        Some(sphere) => {
            // Compute an intersection point. Doing this here avoids unnecessary alloctions.
            let intersection_point = ray.origin + ray.direction * closest_match;
            match sphere.surface {
                // Diffuse surface
                // Find all unoccluded light sources and add up their light contributions.
                Surface::Diffuse { color } => {
                    let mut light_intensity: f32 = 0.0;
                    for light in lights {
                        // Use a shadow ray to check whether a light source is visible:
                        // If the ray between the intersection point and a light source does not
                        // intersect other scene object before the light source, the light source is
                        // unoccluded.
                        let shadow_ray = Ray::from_to(intersection_point, &light.coordinates);
                        let light_distance = (light.coordinates - intersection_point).norm();
                        let mut occluded = false;
                        for other_sphere in spheres {
                            if other_sphere as *const _ != sphere as *const _ {
                                if let Some(distance) = other_sphere.intersect(&shadow_ray) {
                                    if distance.distance < light_distance {
                                        occluded = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if occluded {
                            continue;
                        }
                        let surface_normal = sphere.surface_normal(&intersection_point);
                        let light_intensity_scaling_factor =
                            surface_normal.dot(&shadow_ray.direction);
                        if light_intensity_scaling_factor > 0.0 {
                            light_intensity += light.intensity * light_intensity_scaling_factor;
                        }
                    }
                    color * light_intensity
                }
                // Specular surface: Recurse using a reflected ray.
                Surface::Specular => {
                    let surface_normal = sphere.surface_normal(&intersection_point);
                    let to_source = -ray.direction;
                    let out_direction =
                        2.0 * to_source.dot(&surface_normal) * surface_normal - to_source;
                    trace_ray(
                        &Ray::origin_direction(intersection_point, out_direction),
                        spheres,
                        lights,
                        depth + 1,
                    )
                }
            }
        }
        // no intersection, return color at infinity
        None => infinite_color(&ray),
    }
}
fn trace_ray ( ray : & Ray , spheres : & Vec < Sphere > , lights : & Vec < Light > , depth : u32 ) -> Vector3 < f32 > { let mut closest_match = f32 :: MAX ; let mut closest_sphere : Option < & Sphere > = None ; if depth >= MAX_DEPTH { return infinite_color ( & ray ) ; } // find the closest intersection, if any for sphere in spheres { match sphere . intersect ( & ray ) { None => { } Some ( Intersection { distance } ) => { if distance < closest_match { closest_match = distance ; closest_sphere = Some ( & sphere ) ; } } } } match closest_sphere { Some ( sphere ) => { // Compute an intersection point. Doing this here avoids unnecessary alloctions. let intersection_point = ray . origin + ray . direction * closest_match ; match sphere . surface { // Diffuse surface // Find all unoccluded light sources and add up their light contributions. Surface :: Diffuse { color } => { let mut light_intensity : f32 = 0.0 ; for light in lights { // Use a shadow ray to check whether a light source is visible: // If the ray between the intersection point and a light source does not // intersect other scene object before the light source, the light source is // unoccluded. let shadow_ray = Ray :: from_to ( intersection_point , & light . coordinates ) ; let light_distance = ( light . coordinates - intersection_point ) . norm ( ) ; let mut occluded = false ; for other_sphere in spheres { if other_sphere as * const _ != sphere as * const _ { if let Some ( distance ) = other_sphere . intersect ( & shadow_ray ) { if distance . distance < light_distance { occluded = true ; break ; } } } } if occluded { continue ; } let surface_normal = sphere . surface_normal ( & intersection_point ) ; let light_intensity_scaling_factor = surface_normal . dot ( & shadow_ray . direction ) ; if light_intensity_scaling_factor > 0.0 { light_intensity += light . intensity * light_intensity_scaling_factor ; } } color * light_intensity } // Specular surface: Recurse using a reflected ray. Surface :: Specular => { let surface_normal = sphere . surface_normal ( & intersection_point ) ; let to_source = - ray . direction ; let out_direction = 2.0 * to_source . dot ( & surface_normal ) * surface_normal - to_source ; trace_ray ( & Ray :: origin_direction ( intersection_point , out_direction ) , spheres , lights , depth + 1 , ) } } } // no intersection, return color at infinity None => infinite_color ( & ray ) , } }
Recursive function to compute the color to draw for a given ray and a given scenery,
at recursion depth `depth`.
Recursive function to compute the color to draw for a given ray and a given scenery at recursion depth ` depth ` .
ray
&Ray
spheres
&Vec<Sphere>
lights
&Vec<Light>
depth
u32
ray
&Ray
spheres
&Vec<Sphere>
lights
&Vec<Light>
depth
u32