129 lines
3.5 KiB
Rust
129 lines
3.5 KiB
Rust
#![feature(core_float_math)]
|
|
|
|
mod camera;
|
|
mod objects;
|
|
mod ray;
|
|
mod raytracer;
|
|
mod scenes;
|
|
mod vec3;
|
|
|
|
use std::{env, fs};
|
|
use std::sync::Arc;
|
|
|
|
use crate::camera::Camera;
|
|
use crate::objects::materials::dielectric::Dielectric;
|
|
use crate::objects::materials::lambertian::{Lambertian, Metal};
|
|
use crate::objects::sphere::Sphere;
|
|
use crate::objects::traits::Hittable;
|
|
use crate::ray::Ray;
|
|
use crate::raytracer::render;
|
|
use crate::scenes::scene::Scene;
|
|
use crate::vec3::Vec3;
|
|
use dotenv::dotenv;
|
|
use rand::RngExt;
|
|
|
|
// TODO: implement scene serialization
|
|
fn main() {
|
|
dotenv().ok();
|
|
pretty_env_logger::init();
|
|
|
|
// TODO: better cli parsing
|
|
let mut json_file = "./scenes/scene.json";
|
|
let args: Vec<String> = env::args().collect();
|
|
if args.len() > 1 {
|
|
json_file = &args[1];
|
|
}
|
|
|
|
let json_str = fs::read_to_string(json_file).expect("Reading specified scene file failed!");
|
|
let mut scene: Scene = serde_json::from_str(&json_str).unwrap();
|
|
render(&mut scene);
|
|
return;
|
|
|
|
// random spheres code; thought: make this available as cli flag?
|
|
let ground = Lambertian::rgb(-2.5, 0.5, 0.5, 1.);
|
|
let mut world: Vec<Arc<dyn Hittable>> = vec![Arc::new(Sphere::xyz(
|
|
0.,
|
|
-1000.,
|
|
0.,
|
|
1000.,
|
|
Arc::new(ground),
|
|
))];
|
|
|
|
let mut rng = rand::rng();
|
|
let point = Vec3::new(4., 0.2, 0.);
|
|
for a in -11..11 {
|
|
for b in -11..11 {
|
|
let mat = rng.random_range((0.)..1.);
|
|
let center = Vec3::new(
|
|
a as f32 + 0.9 * rng.random_range((0.)..1.),
|
|
0.2,
|
|
b as f32 + 0.9 * rng.random_range((0.)..1.),
|
|
);
|
|
|
|
if (center - point).length() > 0.9 {
|
|
if mat < 0.8 {
|
|
// diffuse
|
|
world.push(Arc::new(Sphere::new(
|
|
center,
|
|
0.2,
|
|
Arc::new(Lambertian::new(Vec3::random() * Vec3::random(), 1.)),
|
|
)));
|
|
} else if mat < 0.95 {
|
|
// metal
|
|
world.push(Arc::new(Sphere::new(
|
|
center,
|
|
0.2,
|
|
Arc::new(Metal::rgb(
|
|
rng.random_range(0.5..1.),
|
|
rng.random_range(0.5..1.),
|
|
rng.random_range(0.5..1.),
|
|
1.,
|
|
rng.random_range((0.)..0.5),
|
|
)),
|
|
)));
|
|
} else {
|
|
// glass
|
|
world.push(Arc::new(Sphere::new(
|
|
center,
|
|
0.2,
|
|
Arc::new(Dielectric::new(1.5)),
|
|
)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
world.push(Arc::new(Sphere::xyz(
|
|
0.,
|
|
1.,
|
|
0.,
|
|
1.,
|
|
Arc::new(Dielectric::new(1.5)),
|
|
)));
|
|
world.push(Arc::new(Sphere::xyz(
|
|
-4.,
|
|
1.,
|
|
0.,
|
|
1.,
|
|
Arc::new(Lambertian::rgb(0.4, 0.2, 0.1, 1.)),
|
|
)));
|
|
world.push(Arc::new(Sphere::xyz(
|
|
4.,
|
|
1.,
|
|
0.,
|
|
1.,
|
|
Arc::new(Metal::rgb(0.7, 0.6, 0.5, 1., 0.)),
|
|
)));
|
|
|
|
let mut c = Camera::new();
|
|
c.set_fov(20.);
|
|
c.set_anti_alias_rate(23);
|
|
c.set_vup(Vec3::new(0., 1., 0.));
|
|
c.set_look_from(Vec3::new(13., 2., 3.));
|
|
c.set_look_at(Vec3::new(0., 0., 0.));
|
|
c.add_defocus_blur(0.6, 10.);
|
|
|
|
let mut s = Scene::new(c, world, "output.png".to_string(), 1920, 1080, 50);
|
|
render(&mut s);
|
|
}
|