101 lines
3.4 KiB
Rust
101 lines
3.4 KiB
Rust
pub mod vec3;
|
|
pub mod color;
|
|
pub mod ray;
|
|
pub mod sphere;
|
|
pub mod hittable;
|
|
pub mod hittable_list;
|
|
pub mod rtweekend;
|
|
pub mod camera;
|
|
pub mod material;
|
|
|
|
use std::{io::{BufWriter, Write, stdout}, fs::File, time::Instant};
|
|
|
|
use material::Metal;
|
|
|
|
use crate::{
|
|
color::*,
|
|
sphere::*,
|
|
rtweekend::*,
|
|
hittable_list::*,
|
|
vec3::*,
|
|
ray::*,
|
|
hittable::*,
|
|
camera::*, material::{Lambertian, Dielectric},
|
|
};
|
|
|
|
fn ray_color(r: &Ray, world: &mut dyn Hittable, depth: i32) -> Color {
|
|
// Limit the bounces
|
|
if depth <= 0 {
|
|
return Color::new(0.0, 0.0, 0.0);
|
|
}
|
|
|
|
if let Some(rec) = world.hit(r, 0.001, INFINITY) {
|
|
let mut scattered = Ray::new_empty();
|
|
let mut attenuation = Color::new_empty();
|
|
|
|
if rec.mat_ptr.scatter(r, rec, &mut attenuation, &mut scattered) {
|
|
return attenuation * ray_color(&scattered, world, depth - 1);
|
|
}
|
|
return Color::new_empty();
|
|
}
|
|
|
|
let unit_direction: Vec3 = r.direction().unit_vector();
|
|
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() {
|
|
// Image
|
|
let aspect_ratio: f64 = 1.0 / 1.0;
|
|
let image_width: i32 = 512;
|
|
let image_height: i32 = (image_width as f64 / aspect_ratio as f64) as i32;
|
|
let samples_per_pixel: i32 = 100;
|
|
let max_depth: i32 = 4;
|
|
|
|
// World
|
|
let mut world = HittableList::new_empty();
|
|
static MATERIAL_GROUND: Lambertian = Lambertian::new(Color::new(0.3, 0.8, 0.0));
|
|
static MATERIAL_CENTER: Lambertian = Lambertian::new(Color::new(0.1, 0.2, 0.5));
|
|
static MATERIAL_LEFT: Dielectric = Dielectric::new(1.5);
|
|
static MATERIAL_RIGHT: Metal = Metal::new(Color::new(0.8, 0.6, 0.2), 0.0);
|
|
|
|
world.add(Box::new(Sphere::new(Point3::new(0.0, -100.5, -1.0), 100.0, &MATERIAL_GROUND)));
|
|
world.add(Box::new(Sphere::new(Point3::new(0.0, 0.0, -1.0), 0.5, &MATERIAL_CENTER)));
|
|
world.add(Box::new(Sphere::new(Point3::new(-1.0, 0.0, -1.0), -0.5, &MATERIAL_LEFT)));
|
|
world.add(Box::new(Sphere::new(Point3::new(1.0, 0.0, -1.0), 0.5, &MATERIAL_RIGHT)));
|
|
|
|
// Camera
|
|
let cam = Camera::new(120.0, aspect_ratio);
|
|
|
|
// Render
|
|
//let mut rng = rand::thread_rng();
|
|
let now = Instant::now();
|
|
let mut file = BufWriter::new(File::create("img.ppm").expect("File creation failed"));
|
|
|
|
write!(file, "P6\n{image_width} {image_height}\n255\n").expect("Error while writing Magic Byte");
|
|
|
|
for j in (0..image_width).rev() {
|
|
for i in 0..image_height {
|
|
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
|
|
|
|
for _ in 0..samples_per_pixel {
|
|
let u = (i as f64 + random_f64()) / (image_width - 1) as f64;
|
|
let v = (j as f64 + random_f64()) / (image_height - 1) as f64;
|
|
let r: Ray = cam.get_ray(u, v);
|
|
pixel_color += ray_color(&r, &mut world, max_depth)
|
|
}
|
|
write_color_bin(&mut file, pixel_color, samples_per_pixel);
|
|
}
|
|
|
|
print!(
|
|
"[ {:.2} % ]\r",
|
|
(1.0 - ((j + 1) as f64 / image_width as f64)) * 100.0
|
|
);
|
|
stdout().flush().expect("Can flush stdout");
|
|
}
|
|
println!("Took {:.6}ms", now.elapsed().as_millis());
|
|
println!("Took {:.6}s", now.elapsed().as_secs_f64());
|
|
println!("Took {:.6}m", now.elapsed().as_secs_f64() / 60.0);
|
|
println!("Took {:.6}h", now.elapsed().as_secs_f64() / 3600.0);
|
|
} |