The same raytracer as in cpp/README.md, but implemented in rust.
The plan is to take this implementation further as I find developing the raytracer in rust to be a much more enjoyable time (compared to cpp).
This was a good reason and project to learn rust and implement something somewhat complicated too. Also, the fact that the project requires no API, means it is lightweight and easy build. (It also helps that it is quite easy to cross-compile pure rust in multiple platforms)
This project implements the book up till TheNextWeek implementation. I decided not to implement some of the features in this book as I felt they did not really add much value (examples being time for the spheres and perlin noise). I also did implement more features, such as additional planar objects.
Here are some examples:
More generated images here
Requires:
rustup/cargo- clang (Or any linker)
To build and run:
cargo run -r --bin "cli-BINARY_NAME" -- -h- Runs the render with a CLI helper
cargo run -r --bin OTHERS-EXAMPLES- Runs the example with the ppm file contents written to
stdout
- Runs the example with the ppm file contents written to
cargo build -rand run the binary attarget/release/rust-simple-raytracer(.exe)
Mainly developed on VSCode on Linux. Tested to compile and run just fine on linux or windows.
-
The only libraries used are to make interfacing with the project easier
- Clap - For handling CLI
- Rayon - For easier and better multi-threading performance (Needed for more complicated renders)
- indicatif - For progress bar in the terminal
- image - For handling output to a
pngimage- Was simply using the
ppm3format to stdout before this
- Was simply using the
-
.additional/editor- Additional VSCode settings I used -
src- Source Codebin- Specific binary files that are compiled with the ray tracing libraryothers- Contains other examples I did before implementing the CLI helper
I used quite a bit of references for this project, particularly to see how to implement the same things the "rust" way to help me in understand and solidify the harder concepts of rust.
In no particular order:
- dps rust raytracer
- First result you see on google
- His accompanying blog post
- Chris Biscardi's Rust Adventure raytracer project
- The accompanying youtube video
- Very usefully as he talks about implementing the raytracer along with the book, interjecting insights and reasoning for his code in rust (Compared to cpp)
- The accompanying youtube video
For me, compared to c++ it is much easier to see when, where and how a object will/will not be modified.
I attribute this to the fact that in rust the borrow checker makes it clear when object are immutable and/or passed.
A clear example for me was any code which required me to pass in an empty HitRecord object in c++.
This is beacuse this object is modified at multiple places to store the point of intersection and cordinates of the hit on the surface of an object.
Another behaviour is that the functions that want to return the HitRecord might also fail to, because the light ray would hit nothing.
In rust, we have the enum Option to encapsulate returning a nullable value as well as ensure when and where the HitRecord is passed as a mutable reference or created again.
The combination of rustfmt, clippy, rust-analyzer and the compiler makes the development experience much better in rust.
I also cannot over state how much easier it is to setup a development environment in rust as compared to cpp (or most other languages for that matter - I have only really done work with python, c++ and JS/TS). Here are a few points with some direct cross-comparisons with other langauges.
(For context, I mainly do all my development in VSCode and have a very minial vim/neovim setup I use for editing code/text when I need to)
The integration of the langauge server (rust-analyzer) just works with VSCode.
Any option you need as well as the detection of config files(Cargo.toml) works.
I don't need to add in some hack for searching for config paths, I don't need to hope that the extension or langauge server picks up my local version of rust/local libraries or that it has gotten the correct type information.
The hints (and typing) it provides in the editor helps in development and in understanding what is happening (granted this is just baked into rust with it being strongly typed).
For comparison in python:
You would have to install pyliny(or any other linter - i.e. pyright), black, isort and mypy to get to a baseline of what rust has OOTB.
Granted they technically are external libraries, but installing them and running them on every rust project is seamless.
On python, getting these libraries installed system wide is not really an option for development on multiple applications with different python versions.
As for getting them to work on a per project basis, its always a trail and error process, hoping you installed a captiable version with your main python version and libraries you used.
You then pray that no breaking changes are shipped either to the extension or library that breaks functionality of the linter, formatter, or typing, or all of them at once, in your IDE (or worse introduce a single bug error/warning that getting rid of is somewhat troublesome with a hack).
For c++ besides ensuring you have the correct stdlibs and libdev packages installed, you would also probably want to use CMake.
That is because linking and compiling all the different header files and code files is not something you want to write by hand when it gets longer than a single file.
But this takes time away from coding and development of the application to deal with config issues, especially when compiling and running this on different hardware and software. (I am specifically referring to trying to get the same code to compile on different linux systems - arch, ubuntu, as well as different windows systems - mainly my main PC as well as other workstations that I happen to use and would like to continue development on, could be friends or work/school/cloud related systems)


