Raytracer in Rust

We ‘SEE’ an object when light rays from a source of light hit the object from different angles and some of the reflected light rays reach the retina of our eyes. The light rays do not care about the geometry of the object it is hitting. The universal laws of physics determine, what the angle of reflection will be after reflecting.

But in computer graphics, we don’t have such universal laws. There is no light source, no object, and no life. There is just a screen that can show a bunch of pixels that have some colors.

In ray tracing, the RAY of light that was supposed to hit the retina is TRACEd back to an object. An object whose geometry is well known, and the reflections are played in reverse order, to reach the virtual source of light in the virtual world.

In this project, I have played with the algos in Ray Tracing in One Weekend by Peter Shirley and implemented them in Rust.


fn make_image()->String{

    // empty ppm image
    let mut image = String::new();
    
    // image dimensions
    let width:u32 = constants::WIDTH as u32;
    let height:u32 = constants::HEIGHT as u32;

    // camera distance
    let focal = Vec3::new(0.0, 0.0, constants::FOCAL_LENGTH);

    // setting up camera
    let camera = Camera::camera();

    // initializing world
    let mut world = HittableList::new();
    
    // adding 2 spheres to world
    let sphere = Sphere::new(-focal, 0.5);
    let sphere2 = Sphere::new(Vec3::new(0.0, -100.5, -1.0), 100.0);
    world.add(Box::new(sphere2));
    world.add(Box::new(sphere));

    image.push_str(&format!("P3\n{} {}\n255\n",width, height));
    
    // image creator
    for y in (0..height).rev(){
        for x in 0..width{

            let u:f32 = (x as f32) / width as f32;
            let v:f32 = (y as f32) / height as f32;

            // starting a ray from camera to image plane
            let ray: Ray = camera.get_ray(u, v);

            // calculating the color of pixel where ray hits image plane
            let pixel_color = ray_color(&ray, &world, constants::MAX_DEPTH);

            // writing pixel value to image
            write_color(&mut image, &pixel_color);
        }
    }
    image
}

Drawing function that sends a ray to the world to encounter objects.

  1. hello world


“Hello, World!” of graphics. Green goes full on to full off top to bottom. Red goes full on to full off right to left hello_world

  1. blue lerp


Blue lerping from top to bottom blue lerp

  1. hit_sphere


A wild sphere appears with no depth(thus a circle) 3_hit_sphere

  1. hit_sphere_surface_normals


Circle normalises to sphere 4_hit_sphere_surface_normals

  1. hittable_lists


More spheres 6_hittable_lists

  1. diffuse_material


Adding materials to spheres 9_diffuse_material

  1. shadow_acne


Shadows! 9a_shadow_acne

  1. lambertian_reflection


Shadows and relection(failed attempt) 9b_lambertian_reflection

  1. corrected_lambertian_reflection


meh 9c_corrected_lambertian_reflection

Will definitely visit again to improve the results.