rustracer/src/main.rs
2022-07-02 06:32:03 +02:00

105 lines
3.3 KiB
Rust

use crate::camera::Camera;
use crate::hittable::{Hittable, Sphere};
use crate::ray::Ray;
use crate::vec3::{Color, Point3, Vec3};
use rand::distributions::{Distribution, Uniform};
use crate::material::{Dielectric, Lambertian, Material, Metal};
mod vec3;
mod ray;
mod hittable;
mod material;
mod camera;
fn random_scene() -> Vec<Box<dyn Hittable>> {
let mut world:Vec<Box<dyn Hittable>> = Vec::new();
let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
let ground = Sphere {
center: Point3::new(0.0, -1000.0, 0.0),
radius: 1000.0,
material: material_ground
};
world.push(Box::new(ground));
let unit_range = Uniform::from(0.0..1.0);
let fuzz_range = Uniform::from(0.0..0.5);
let mut rng = rand::thread_rng();
let p = Point3::new(4.0, 0.2, 0.0);
for a in -1..11 {
for b in -11..11 {
let choose_material = unit_range.sample(&mut rng);
let center = Point3::new(
(a as f64) + 0.9*unit_range.sample(&mut rng),
0.2,
(b as f64) + 0.9*unit_range.sample(&mut rng));
if (center - p).length() < 0.9 {
continue;
}
let material = match choose_material {
_ if choose_material < 0.8 => Material::Lambertian(Lambertian::new(
Color::random(0.0, 1.0) * Color::random(0.0, 1.0))),
_ if choose_material < 0.95 => Material::Metal(Metal::new(
Color::random(0.5, 1.0),
fuzz_range.sample(&mut rng))),
_ => Material::Dielectric(Dielectric::new(1.5)),
};
let sphere = Box::new(Sphere {
center,
radius: 0.2,
material
});
world.push(sphere);
}
}
world
}
fn main() {
// Image
const ASPECT_RATIO: f64 = 3.0 / 2.0;
const IMAGE_WIDTH: i32 = 1200;
const IMAGE_HEIGHT: i32 = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as i32;
const SAMPLES_PER_PIXEL: i32 = 10;
const MAX_DEPTH: i32 = 50;
let look_from = Point3::new(13.0, 2.0, 3.0);
let look_at = Point3::new(0.0, 0.0, 0.0);
let focus_dist = 10.0;
// Camera
let cam = Camera::new(
look_from,
look_at,
Vec3::new(0.0, 1.0, 0.0),
ASPECT_RATIO,
20.0,
0.1,
focus_dist);
// World
let world= random_scene();
println!("P3\n{} {}\n255", IMAGE_WIDTH, IMAGE_HEIGHT);
let between = Uniform::from(0.0..1.0);
let mut rng = rand::thread_rng();
for j in (0..IMAGE_HEIGHT).rev() {
eprint!("\rScanlines remaining: {} ", j);
for i in 0..IMAGE_WIDTH {
let mut color = Color::default();
for s in 0..SAMPLES_PER_PIXEL {
let random_number = between.sample(&mut rng);
let u = (i as f64 + random_number) / (IMAGE_WIDTH - 1) as f64;
let v = (j as f64 + random_number) / (IMAGE_HEIGHT - 1) as f64;
let ray = cam.get_ray(u, v);
if i == 200 && (j == 112 || j == 113) {
let tt = 0;
}
color += ray.pixel_color(&world, MAX_DEPTH);
}
color.write_color(SAMPLES_PER_PIXEL);
}
}
eprintln!("\nDone");
}