aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils.rs
blob: 7e8c51f460411cf26d9b002151b5d6e3df5aedea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use cgmath::prelude::*;
use cgmath::{dot, vec3, Vector3};
use rand::prelude::*;
use std::f64::consts::PI;

pub fn clamp(x: f64, min: f64, max: f64) -> f64 {
    if x < min {
        min
    } else if x > max {
        max
    } else {
        x
    }
}

pub fn print_colour(colour: &Vector3<f64>, samples: i32) {
    let scolour = colour.map(|x| (x / samples as f64).sqrt());
    println!(
        "{} {} {}",
        (256.0 * clamp(scolour.x, 0.0, 0.999)) as i32,
        (256.0 * clamp(scolour.y, 0.0, 0.999)) as i32,
        (256.0 * clamp(scolour.z, 0.0, 0.999)) as i32
    )
}

pub fn random_vector3(rng: &mut ThreadRng, min: f64, max: f64) -> Vector3<f64> {
    vec3(
        rng.gen_range(min, max),
        rng.gen_range(min, max),
        rng.gen_range(min, max),
    )
}

pub fn random_in_unit_sphere(rng: &mut ThreadRng) -> Vector3<f64> {
    loop {
        let p = random_vector3(rng, -1.0, 1.0);
        if p.magnitude2() <= 1.0 {
            return p;
        }
    }
}

pub fn random_unit_vector(rng: &mut ThreadRng) -> Vector3<f64> {
    let a = rng.gen_range(0.0, 2.0 * PI);
    let z = rng.gen_range(-1.0, 1.0);
    let r = ((1.0 - z * z) as f64).sqrt();
    vec3(r * a.cos(), r * a.sin(), z)
}

pub fn random_in_hemisphere(rng: &mut ThreadRng, normal: &Vector3<f64>) -> Vector3<f64> {
    let in_unit_sphere = random_in_unit_sphere(rng);
    if dot(in_unit_sphere, *normal) > 0.0 {
        in_unit_sphere
    } else {
        -in_unit_sphere
    }
}

pub fn random_in_unit_disk(rng: &mut ThreadRng) -> Vector3<f64> {
    loop {
        let p = vec3(rng.gen_range(-1.0, 1.0), rng.gen_range(-1.0, 1.0), 0.0);
        if p.magnitude2() < 1.0 {
            return p;
        }
    }
}

pub fn reflect(v: &Vector3<f64>, n: &Vector3<f64>) -> Vector3<f64> {
    v - 2.0 * dot(*v, *n) * n
}

pub fn refract(uv: &Vector3<f64>, n: &Vector3<f64>, etai_over_etat: f64) -> Vector3<f64> {
    let cos_theta = dot(-1.0 * uv, *n);
    let r_out_parallel = etai_over_etat * (uv + cos_theta * n);
    let r_out_perp = -(1.0 - r_out_parallel.magnitude2()).sqrt() * n;
    r_out_parallel + r_out_perp
}

pub fn schlick(cosine: f64, ref_idx: f64) -> f64 {
    let r0 = (1.0 - ref_idx) / (1.0 + ref_idx);
    let r0sq = r0 * r0;
    r0sq + (1.0 - r0) * (1.0 - cosine).powi(5)
}