aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 1a0b001db4e0725b840cb863fefb8f49a1bda530 (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
84
use cgmath::prelude::*;
use cgmath::{Vector3, vec3};
use rand::prelude::*;
use std::f64::consts::PI;

mod camera;
mod hittable;
mod material;
mod ray;
mod render;
mod scene;
mod sphere;
mod utils;

pub fn random_scene(rng: &mut ThreadRng) -> scene::Scene {
    let mut scene = scene::Scene::new();

    scene.add(Box::new(sphere::Sphere::new(
        vec3(0.0, -1000.0, 0.0), 1000.0, Box::new(material::Lambertian::new(vec3(0.5, 0.5, 0.5))))));

    for a in -11 .. 11 {
        for b in -11 .. 11 {
            let choose_mat: f64 = rng.gen();
            let center = vec3(a as f64 + 0.9*rng.gen::<f64>(), 0.2, b as f64 + 0.9*rng.gen::<f64>());
            if (center - vec3(4.0, 0.2, 0.0)).magnitude() > 0.9 {
                if choose_mat < 0.8 {
                    // diffuse
                    let albedo = utils::random_vector3(rng, 0.0, 1.0).mul_element_wise(utils::random_vector3(rng, 0.0, 1.0));
                    scene.add(
                        Box::new(sphere::Sphere::new(center, 0.2, Box::new(material::Lambertian::new(albedo)))));
                } else if choose_mat < 0.95 {
                    // metal
                    let albedo = utils::random_vector3(rng, 0.5, 1.0);
                    let fuzz = rng.gen_range(0.0, 0.5);
                    scene.add(
                        Box::new(sphere::Sphere::new(
                            center, 0.2, Box::new(material::Metal::new(albedo, fuzz)))));
                } else {
                    // glass
                    scene.add(Box::new(sphere::Sphere::new(
                        center, 0.2, Box::new(material::Dielectric::new(1.5)))));
                }
            }
        }
    }

    scene.add(Box::new(sphere::Sphere::new(
        vec3(0.0, 1.0, 0.0), 1.0, Box::new(material::Dielectric::new(1.5)))));

    scene.add(
        Box::new(sphere::Sphere::new(vec3(-4.0, 1.0, 0.0), 1.0,
                                     Box::new(material::Lambertian::new(vec3(0.4, 0.2, 0.1))))));

    scene.add(
        Box::new(sphere::Sphere::new(
            vec3(4.0, 1.0, 0.0), 1.0, Box::new(material::Metal::new(vec3(0.7, 0.6, 0.5), 0.0)))));

    scene
}

fn main() {
    let image_width = 1200;
    let image_height = 800;
    let samples = 100;
    let max_depth = 50;
    let aspect_ratio = image_width as f64 / image_height as f64;

    println!("P3\n{} {}\n255", image_width, image_height);
    let mut rng = thread_rng();

    let scene = random_scene(&mut rng);

    let lookfrom = vec3(13.0, 2.0, 3.0);
    let lookat = vec3(0.0, 0.0, 0.0);
    let vup = vec3(0.0, 1.0, 0.0);
    let dist_to_focus = 10.0;
    let aperture = 0.1;
    let camera = camera::Camera::new(&lookfrom, &lookat, &vup,
                                     20.0 * PI / 180.0, aspect_ratio, aperture, dist_to_focus);

    render::render(&scene, camera, image_height, image_width, samples, max_depth, &mut rng);

    eprintln!("\nDone")
}