This project is a rust
implementation of a cpu-based raytracer based on the series:
This is a personal project to learn rust
and my first real project in rust
. As usual, some implementation hints from other similar projects were taken, but the work has been implemented mostly based on the original C++ implementation from the books.
Open tasks:
- Book 2
- Polish the demo scene code
- Book 3
- Implement pdf based sampling
- Implement sampling from light sources
- Update material functions for new sampling method
- Remove spickles induced by incorrect color samples (resulting in not-a-number values)
- Rewrite BVH to work with indices to objects instead of object containers
- Create a more organized structure for the different scenes (perhaps serialize to/from JSON)
- Implement additional tests for material functions
The project can be built and executed using cargo
.
cargo build --release
cargo run --release
To speed up the rendering process, the raytracer is multithreaded, allowing us to evaluate several pixels in parallel threads.
Rayon is used for multithreading, we iterate over each line and map with a parallel iterator over each pixel per line. It was not possible to use a parallel for iterator for all pixels, hence why the parallel iterator is applied for each line.
for j in (0..image_height).rev() {
let pixels: Vec<Vector3<f32>> = (0..image_width).into_par_iter().map(|i| {
get_pixel_color(
image_width,
image_height,
samples_per_pixel,
&cam,
&world,
max_depth,
i,
j,
)
}).collect();
for pix in pixels {
write_color(&mut f, &pix);
}
}
During my brief testing, I also tried calculating each sample per pixel in a seperate thread, but this did not yield any significant speed up. It could be that a single sample is very fast to evaluate with just a few objects in the scene and therefore the overhead of starting of managing the threads outweighs the benefits.