profile picture

Ray Tracing with Rust and WebAssembly

January 17, 2020 - rust webassembly

Sprite Atlas

I have been working through the book The Ray Tracer Challenge: A Test-Driven Guide to Your First 3D Renderer by Jamis Buck. It is a fantastic book, there is almost no code (other than a little bit of pseudocode), instead there is an explanation of how to build a Whitted ray tracer and a large number of unit tests to walk you through implementing it yourself.

I decided to try to implement the ray tracer in Rust and compile to both a native app and WebAssembly. Source code is available at GitHub. Currently i've worked through chapter 9 (of 17) so there are a number of features my implementation is missing (and I haven't done any optimization yet).

Unsurprisingly the native app is much faster (by about an order of magnitude by my very unscientific measurements), but I was quite pleased how easy it was to generate the WebAssembly code using Rust.

Above is a pregenerated image, but you can click the button below to generate a smaller lower quality picture on demand. I am using Web Workers to do the rendering calculations in multiple threads (each Web Worker runs some WebAssembly).

If you are using Safari there is an issue with window.navigator.hardwareConcurrency and this app will default to a single thread. Try in a browser like Firefox or Chrome to see better performance.

I have been quite impressed with the Rust tooling and how easy it was to generate a WebAssembly app in the browser. I'm now intrigued with the idea of being able to write WebAssembly modules in languages like C/C++/Rust/Go etc which can interop with each other, and then have the ability to write a smallish frontend in JavaScript or Python (using something like the Wasmtime package) to glue it all together.