raytracer/src/main.rs

83 lines
2.3 KiB
Rust

pub mod camera;
pub mod display;
pub mod hit;
pub mod ppm_format;
mod ray;
pub mod shapes;
mod vec;
use std::io::{stderr, Write};
use hit::Hit;
use rand::Rng;
use ray::Ray;
use vec::{Color, Point3, Vec3};
use crate::{camera::Camera, hit::World, ppm_format::Header, shapes::sphere::Sphere};
fn ray_color(r: &Ray, world: &World) -> Color {
if let Some(rec) = world.hit(r, 0.0, f64::INFINITY) {
0.5 * (rec.normal + Color::new(1.0, 1.0, 1.0))
} else {
let unit_direction = r.direction().normalized();
let t = 0.5 * (unit_direction.y() + 1.0);
(1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0)
}
}
fn main() {
let xyz = "1280x720@60";
let display_info = display::parse_display_string(xyz).unwrap();
const SAMPLES_PER_PIXEL: u64 = 8;
// World
let mut world = World::new();
world.push(Box::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5)));
world.push(Box::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0)));
// Camera
let cam = Camera::new();
let header = Header {
ppm_format: ppm_format::PpmFormat::P3,
width: display_info.width,
height: display_info.height,
max_color_value: 255,
};
println!("{}", header);
use std::time::Instant;
let now = Instant::now();
// Code block to measure.
let mut rng = rand::thread_rng();
{
for j in (0..display_info.height).rev() {
eprint!("\rScanlines remaining: {:3}", display_info.height - j - 1);
stderr().flush().unwrap();
for i in 0..display_info.width {
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
for _ in 0..SAMPLES_PER_PIXEL {
let random_u: f64 = rng.gen();
let random_v: f64 = rng.gen();
let u = ((i as f64) + random_u) / ((display_info.width - 1) as f64);
let v = ((j as f64) + random_v) / ((display_info.height - 1) as f64);
let r = cam.get_ray(u, v);
pixel_color += ray_color(&r, &world);
}
println!("{}", pixel_color.format_color(SAMPLES_PER_PIXEL));
}
}
let elapsed = now.elapsed();
eprintln!("\nElapsed: {:.2?}", elapsed);
}
eprintln!("\nDone.");
}