My raytracer: shrimpray


Been wanting to learn more about rust so I followed the Raytracing in One Weekend book and wrote a raytracer called shrimpray: *click*

I tried avoiding passing mutables to functions so lots of Option<T> and structs instantiated in the function are returned instead. I'm hoping this is a more rust style of things.

This is my first project in rust so any advice would be cool like improving performance and stuff :slightly_smiling_face:

2 Likes

Looks pretty good. You talk about avoiding mutable, but what would you consider the alternative to returning options? Optionally writing to a passed mutable pointer? Ew, we have an optimizer to pick the best return method for us.

Only thing I noticed is that it's a bit better to keep the thread_rng value around, because each call involves incrementing and decrementing a reference count. Luckily it's not an atomic reference count, so it probably doesn't really matter, and it isn't in the expensive part of the code either.

pub fn rand_float() -> f32 {
    let mut rng = rand::thread_rng();
    rng.gen::<f32>()
}

(also in this case the compiler can deduce you want an f32, so you can just do rng.gen())

Thanks, there's like two more books in the series and I wanna aim to get through them all.

Yeah the C++ code in the book would take in mutable pointers and return a true or false if it modified stuff like this:

bool refract(const vec3& v, const vec3& n, float ni_over_nt, vec3& refracted) {
    vec3 uv = unit_vector(v);
    float dt = dot(uv, n);
    float discriminant = 1.0 - ni_over_nt*ni_over_nt*(1-dt*dt);
    if (discriminant > 0) {
        refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant);
        return true;
    }
    else
        return false;
}

And okay, gonna look into whether thread_rng can be stuffed into a global or static variable.

Don't worry about that, it already is inside the function, it just increments a reference count on every access.