Raytracing in Rust
Overview
On June 1st, 2025, I was bored and ran out of ideas for things to do on a Sunday. I remembered my friend telling me about a project he did where he implemented ray tracing following an online book. I don’t know why or how I remembered that. I immediately message him to get the link to the book.
The Book: Ray Tracing in One Weekend
The book is in C++. I thought it would be a good challenge to implement it in Rust. and maybe improve my Rust knowledge along the way.
I am not sure if I will be able to pull it off in a single weekend. but I am going to keep at it without a deadline of some sort. I aim to simply finish the implementation in Rust.
As part of the learning, I will be collecting a lot of useful resources. I am going to link all of them in the resources section here.
Just realized from the GitHub link for the book that this is a series of books. https://github.com/RayTracing/raytracing.github.io/
Let’s see if we can follow along for The Rest of Your Life.
Resources
| Name | Link |
|---|---|
| The Book | Ray Tracing in One Weekend |
| Computer Graphics Codex | https://graphicscodex.com/ |
| The Rust Book | https://doc.rust-lang.org/book/title-page.html |
With that out of the way, lets start our first Milestone.
Output an Image
The Goal of this chapter is to create a image file with colour information for each pixel randomly generated by our function. sounds complicated but in reality its very simple.
First lets setup the initial height and width of the image.
const IMAGE_WIDTH: u32 = 256;const IMAGE_HEIGHT: u32 = 256;
u32here refers to the dataType, we are dealing with 32 bit integer here. the letterudenotes that this is a unsigned integer. which simply means that we will not require negative values in this variable. if we require negative values in a variable then it should be declared as asigned variablei32
According to the book we were supposed to write the pixel data into a ppm file. which is a awful image format. I am going to try and write png image. unlike C++ we have a rich developer eco system with packages (crates) that we can use to write a image file. I am going to use the crate Image for our use case.
The final code looks this:
use image::{ImageBuffer, Rgb, RgbImage};
fn main() { const IMAGE_WIDTH: u32 = 256; const IMAGE_HEIGHT: u32 = 256; // create a pixel map for given image witdht and height let mut buffer: RgbImage = ImageBuffer::new(IMAGE_WIDTH, IMAGE_HEIGHT);
// Iterate over the coordinates and pixels of the image for (x, y, pixel) in buffer.enumerate_pixels_mut() { let r = x as f64 / (IMAGE_WIDTH - 1) as f64; let g = y as f64 / (IMAGE_HEIGHT - 1) as f64; let b = 0.25;
let ir = (255.999 * r) as u8; let ig = (255.999 * g) as u8; let ib = (255.999 * b) as u8;
*pixel = Rgb([ir, ig, ib]); } // create a std output stream with pixle information to write to file. buffer.save("image.png").unwrap(); // create a file.}When run this code, it will generate a 256x256 png image with a colour gradient.
Error Handling
Unwrapping should be OK if the result is never an error, but writing to a file can always fail. Let’s write either “Done” or our own error message depending on the result:
match buffer.save("image.png") { Err(e) => eprintln!("Error writing file: {}", e), Ok(()) => println!("Done."),};And now we are finally done. only with this chapter