diff --git a/scenes/highDef.json b/scenes/highDef.json new file mode 100644 index 0000000..5f89630 --- /dev/null +++ b/scenes/highDef.json @@ -0,0 +1,37 @@ +{ + "camera": { + "image_width": 1920, + "image_height": 1080, + "anti_alias_rate": 23, + "max_depth": 50, + "fov": 20.0, + "look_from": { "x": -10, "y": 5, "z": 10 }, + "look_at": { "x": 0.0, "y": 0.0, "z": -1.0 }, + "vup": { "x": 0.0, "y": 1.0, "z": 0.0 }, + "defocus_blur": false, + "defocus_angle": 2, + "focus_dist": 15.68 + }, + "materials": [ + { "type": "metal", "albedo": { "x": 0.2, "y": 0.4, "z": 0.8 }, "prob": 1.0, "fuzz": 0.1 }, + { "type": "metal", "albedo": { "x": 0.7, "y": 0.4, "z": 0.2 }, "prob": 1.0, "fuzz": 0.1 }, + { "type": "lambertian", "albedo": { "x": 0.8, "y": 0.8, "z": 0.0 }, "prob": 1.0 }, + { "type": "lambertian", "albedo": { "x": 0.1, "y": 0.2, "z": 0.5 }, "prob": 1.0 }, + { "type": "dielectric", "refraction_index": 1.5}, + { "type": "dielectric", "refraction_index": 0.67}, + { "type": "metal", "albedo": { "x": 0.8, "y": 0.6, "z": 0.2 }, "prob": 1.0, "fuzz": 1.0 } + + ], + "objects": [ + { "type": "sphere", "center": { "x": 0, "y": 0.7, "z": -0.4 }, "radius": 0.2, "material": 0}, + { "type": "sphere", "center": { "x": 0.0, "y": 0.5, "z": -0.8 }, "radius": 0.1, "material": 1}, + { "type": "sphere", "center": { "x": 0.0, "y": -100.5, "z": -1.0 }, "radius": 100.0, "material": 2}, + { "type": "sphere", "center": { "x": 0.0, "y": 0.0, "z": -1.2 }, "radius": 0.5, "material": 3}, + { "type": "sphere", "center": { "x": -1, "y": 0, "z": -1 }, "radius": 0.4, "material": 5}, + { "type": "sphere", "center": { "x": 1, "y": 0, "z": -1 }, "radius": 0.5, "material": 6}, + { "type": "sphere", "center": { "x": 20, "y": 7, "z": -15 }, "radius": 10.5, "material": 0} + ] +} + + + diff --git a/scenes/scene.json b/scenes/scene.json index c8a95a6..e0fe06a 100644 --- a/scenes/scene.json +++ b/scenes/scene.json @@ -2,8 +2,8 @@ "camera": { "image_width": 1920, "image_height": 1080, - "anti_alias_rate": 23, - "max_depth": 100, + "anti_alias_rate": 2, + "max_depth": 10, "fov": 20.0, "look_from": { "x": -10, "y": 5, "z": 10 }, "look_at": { "x": 0.0, "y": 0.0, "z": -1.0 }, diff --git a/src/camera.rs b/src/camera.rs index 05f7838..e5089da 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -183,7 +183,7 @@ impl Camera { fn defocus_disk_sample(&self) -> Vec3 { let p = Vec3::random_in_unit_disk(); - return self.look_from + (p.x() * self.defocus_disk_u) + (p.y() * self.defocus_disk_v); + self.look_from + (p.x() * self.defocus_disk_u) + (p.y() * self.defocus_disk_v) } pub fn render(&mut self, hittables: &Vec>) { @@ -209,7 +209,7 @@ impl Camera { let ray_orig = if self.defocus_angle > 0. { self.defocus_disk_sample() } else {self.look_from}; let ray_dir = pixel_loc - ray_orig; let r = Ray::new(ray_orig, ray_dir); - pixel_colour += self.ray_colour(&hittables, &r, self.max_depth); + pixel_colour += self.ray_colour(hittables, &r, self.max_depth); } } @@ -220,7 +220,7 @@ impl Camera { } info!("Writing image file..."); - imgbuf.save("output.png").unwrap(); + imgbuf.save("output2.png").unwrap(); } fn ray_colour(&self, hittables: &Vec>, r: &Ray, depth: u32) -> Colour { diff --git a/src/main.rs b/src/main.rs index 3433689..a0fec5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod ray; mod scenes; mod vec3; +use std::fs; use std::sync::Arc; use crate::camera::Camera; @@ -14,9 +15,9 @@ use crate::objects::materials::lambertian::{Lambertian, Metal}; use crate::objects::sphere::Sphere; use crate::objects::traits::Hittable; use crate::ray::Ray; +use crate::scenes::scene::Scene; use crate::vec3::Vec3; use dotenv::dotenv; -use pretty_env_logger; use rand::RngExt; // TODO: implement scene serialization @@ -25,10 +26,11 @@ fn main() { pretty_env_logger::init(); // TODO: use cli arg for scenefile - // let json_file = "./scenes/scene.json"; - // 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(); - // scene.render(); + let json_file = "./scenes/scene.json"; + 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(); + scene.render(); + return; // random spheres code; thought: make this available as cli flag? let ground = Lambertian::rgb(0.5, 0.5, 0.5, 1.); diff --git a/src/objects/hit.rs b/src/objects/hit.rs index a01b067..b7fb6ff 100644 --- a/src/objects/hit.rs +++ b/src/objects/hit.rs @@ -17,11 +17,11 @@ pub struct Hit { impl Hit { pub fn new(t: f32, p: Vec3, n: Vec3, mat: Arc, front_face: bool) -> Self { Self { - t: t, - p: p, + t, + p, n: if front_face { n } else { -n }, - mat: mat, - front_face: front_face, + mat, + front_face, } } @@ -57,6 +57,6 @@ impl Hit { } } } - return closest; + closest } } diff --git a/src/objects/materials/dielectric.rs b/src/objects/materials/dielectric.rs index a8344a1..46051f5 100644 --- a/src/objects/materials/dielectric.rs +++ b/src/objects/materials/dielectric.rs @@ -17,15 +17,15 @@ pub struct Dielectric { impl Dielectric { pub fn new(refraction_index: f32) -> Self { Self { - refraction_index: refraction_index, + refraction_index, } } - fn _reflectance(cos: f32, refraction_index: f32) -> f32 { + fn reflectance(cos: f32, refraction_index: f32) -> f32 { // Shlick's approximation let mut r0 = (1. - refraction_index) / (1. + refraction_index); r0 *= r0; - return r0 + (1. - r0) * (1. - cos).powf(5.); + r0 + (1. - r0) * (1. - cos).powf(5.) } } @@ -45,13 +45,12 @@ impl Material for Dielectric { let sin_theta = sqrt(1. - cos_theta * cos_theta); let cannot_refract = ri * sin_theta > 1.; - let dir: Vec3; let mut rng = rand::rng(); - if cannot_refract || Dielectric::_reflectance(cos_theta, ri) > rng.random::() { - dir = unit.reflect(hit.n()); + let dir = if cannot_refract || Dielectric::reflectance(cos_theta, ri) > rng.random::() { + unit.reflect(hit.n()) } else { - dir = unit.refract(hit.n(), ri); - } + unit.refract(hit.n(), ri) + }; Some((Ray::new(*hit.p(), dir), Colour::new(1., 1., 1.))) } } diff --git a/src/objects/materials/lambertian.rs b/src/objects/materials/lambertian.rs index 23a01db..9146b43 100644 --- a/src/objects/materials/lambertian.rs +++ b/src/objects/materials/lambertian.rs @@ -16,21 +16,21 @@ pub struct Lambertian { impl Lambertian { pub fn new(albedo: Colour, prob: f32) -> Self { Self { - albedo: albedo, - prob: prob, + albedo, + prob, } } pub fn rgb(r: f32, g: f32, b: f32, prob: f32) -> Self { Self { albedo: Colour::new(r, g, b), - prob: prob, + prob, } } } impl Material for Lambertian { - fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)> { + fn scatter(&self, hit: &Hit, _ray: &Ray) -> Option<(Ray, Colour)> { let mut rng = rand::rng(); if self.prob >= rng.random::() { let mut dir = *hit.n() + Vec3::random_unit(); @@ -40,7 +40,7 @@ impl Material for Lambertian { let scattered = Ray::new(*hit.p(), dir); return Some((scattered, self.albedo)); } - return None; + None } } @@ -54,17 +54,17 @@ pub struct Metal { impl Metal { pub fn new(albedo: Colour, prob: f32, fuzz: f32) -> Self { Self { - albedo: albedo, - prob: prob, - fuzz: fuzz, + albedo, + prob, + fuzz, } } pub fn rgb(r: f32, g: f32, b: f32, prob: f32, fuzz: f32) -> Self { Self { albedo: Colour::new(r, g, b), - prob: prob, - fuzz: fuzz, + prob, + fuzz, } } } @@ -77,6 +77,6 @@ impl Material for Metal { refl = refl.get_unit() + self.fuzz * Vec3::random_unit(); return Some((Ray::new(*hit.p(), refl), self.albedo)); } - return None; + None } } diff --git a/src/objects/materials/traits.rs b/src/objects/materials/traits.rs index 2b7d519..b6593e0 100644 --- a/src/objects/materials/traits.rs +++ b/src/objects/materials/traits.rs @@ -1,6 +1,6 @@ use crate::{objects::hit::Hit, ray::Ray, vec3::Colour}; use std::fmt::Debug; -pub trait Material: Debug { +pub trait Material: Debug + Send + Sync{ fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)>; } diff --git a/src/objects/sphere.rs b/src/objects/sphere.rs index 0392a12..be6fb80 100644 --- a/src/objects/sphere.rs +++ b/src/objects/sphere.rs @@ -2,7 +2,6 @@ use core::f32::math::sqrt; use std::fmt::{self, Debug}; use std::sync::Arc; -use serde::Deserialize; use crate::objects::hit::Hit; use crate::objects::materials::traits::Material; @@ -16,6 +15,7 @@ pub struct Sphere { material: Arc, } + impl Debug for Sphere { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Sphere") @@ -29,7 +29,7 @@ impl Debug for Sphere { impl Sphere { pub fn new(center: Vec3, r: f32, mat: Arc) -> Self { Self { - center: center, + center, radius: r, material: mat, } @@ -42,16 +42,6 @@ impl Sphere { material: mat, } } - - pub fn center(&self) -> &Vec3 { - &self.center - } - - pub fn set_center(&mut self, center: Vec3) { - if self.center != center { - self.center = center; - } - } } impl Hittable for Sphere { @@ -83,12 +73,4 @@ impl Hittable for Sphere { fn normal_at(&self, p: &Vec3) -> Vec3 { (*p - self.center).get_unit() } - - fn inside(&self, p: &Vec3) -> bool { - (*p - self.center).length() < self.radius - } - - fn closest_on_surface(&self, p: &Vec3) -> Vec3 { - self.normal_at(p) * self.radius - } } diff --git a/src/objects/traits.rs b/src/objects/traits.rs index fc4cdc5..bfc1c4e 100644 --- a/src/objects/traits.rs +++ b/src/objects/traits.rs @@ -4,10 +4,7 @@ use crate::objects::hit::Hit; use crate::Ray; use crate::Vec3; -pub trait Hittable: Debug { +pub trait Hittable: Debug + Send + Sync { fn hit(&self, r: &Ray) -> Option; fn normal_at(&self, p: &Vec3) -> Vec3; - // fn intersect(&self, o: &H) -> bool; - fn inside(&self, p: &Vec3) -> bool; - fn closest_on_surface(&self, p: &Vec3) -> Vec3; } diff --git a/src/ray.rs b/src/ray.rs index 7cfea1e..6f651d4 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -8,8 +8,8 @@ pub struct Ray { impl Ray { pub fn new(origin: Vec3, dir: Vec3) -> Self { Self { - origin: origin, - dir: dir, + origin, + dir, } } diff --git a/src/vec3.rs b/src/vec3.rs index 4046538..84fe159 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -83,7 +83,7 @@ impl Vec3 { } pub fn length_squared(&self) -> f32 { - (self.x * self.x + self.y * self.y + self.z * self.z) as f32 + self.x * self.x + self.y * self.y + self.z * self.z } pub fn dot(&self, other: &Self) -> f32 { @@ -123,7 +123,7 @@ impl Vec3 { let r_out_perp = etai_over_etat * (*self + cos_theta * n); let r_out_parr = -sqrt((1. - r_out_perp.length_squared()).abs()) * n; - return r_out_perp + r_out_parr; + r_out_perp + r_out_parr } pub fn output(self) -> image::Rgb {