From 2ba85de59f63a0cb28ec8375e2b5ce555517eb13 Mon Sep 17 00:00:00 2001 From: JonOfUs Date: Tue, 28 Jun 2022 18:23:22 +0200 Subject: [PATCH] Finalize tutorial --- Cargo.lock | 40 +++++++-------- src/camera.rs | 53 ++++++++++++++------ src/main.rs | 130 +++++++++++++++++++++++++++++++++++++------------ src/utility.rs | 2 +- src/vec3.rs | 12 ++++- 5 files changed, 170 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3de2d9f..2b12b67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -82,26 +82,26 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -121,9 +121,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -161,12 +161,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.126" @@ -214,9 +208,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-integer", @@ -242,6 +236,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + [[package]] name = "png" version = "0.17.5" @@ -331,6 +331,6 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/src/camera.rs b/src/camera.rs index eea04c0..1661a58 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -5,34 +5,59 @@ pub struct Camera { lower_left_corner: Point3, horizontal: Vec3, vertical: Vec3, + u: Vec3, + v: Vec3, + w: Vec3, + lens_radius: f64, + } impl Camera { - pub fn new() -> Self { - let aspect_ratio = 16.0 / 9.0; - let viewport_height = 2.0; + pub fn new( + lookfrom: Point3, + lookat: Point3, + vup: Vec3, + vfov: f64, // vertical field of view in degrees + aspect_ratio: f64, + aperture: f64, + focus_dist: f64, + ) -> Self { + let theta = vfov.to_radians(); + let h = (theta/2.0).tan(); + let viewport_height = 2.0*h; let viewport_width = aspect_ratio * viewport_height; - let focal_length = 1.0; - let origin = Point3::new(0.0, 0.0, 0.0); - let horizontal = Vec3::new(viewport_width, 0.0, 0.0); - let vertical = Vec3::new(0.0, viewport_height, 0.0); + let w = Vec3::unit_vector(lookfrom - lookat); + let u = Vec3::unit_vector(Vec3::cross(vup, w)); + let v = Vec3::cross(w, u); + + let origin = lookfrom; + let horizontal = focus_dist * viewport_width * u; + let vertical = focus_dist * viewport_height * v; + let lower_left_corner = origin - horizontal/2.0 - vertical/2.0 - focus_dist*w; + + let lens_radius = aperture / 2.0; return Camera { origin, horizontal, vertical, - lower_left_corner: origin - - horizontal / 2.0 - - vertical / 2.0 - - Vec3::new(0.0, 0.0, focal_length), + lower_left_corner, + u, + v, + w, + lens_radius, }; } pub fn get_ray(&self, u: f64, v: f64) -> Ray { - Ray::new( - self.origin, - self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin, + + let rd = self.lens_radius * Vec3::random_in_unit_disk(); + let offset = rd.x() * self.u + rd.y() * self.v; + + return Ray::new( + self.origin + offset, + self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin - offset, ) } } diff --git a/src/main.rs b/src/main.rs index 3cb3f62..328e9e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,50 +44,92 @@ fn ray_color(r: &Ray, world: &HittableList, depth: u32) -> Color { return (1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0); } -fn main() { - // File - let mut default_file = "image.ppm"; - - // Image - let aspect_ratio = 16.0 / 9.0; - let image_width = 1000; - let image_height = (image_width as f64 / aspect_ratio) as u32; - let samples_per_pixel = 100_u32; - let max_depth = 50; - - // World +fn random_world() -> HittableList { let mut world = HittableList::new(); - let material_ground = Arc::new(Lambertian::new(&Color::new(0.2, 0.3, 0.0))); - let material_center = Arc::new(Lambertian::new(&Color::new(0.7, 0.1, 0.2))); + let material_ground = Arc::new(Lambertian::new(&Color::new(0.1, 0.1, 0.1))); + + //let material_center = Arc::new(Lambertian::new(&Color::new(0.7, 0.1, 0.2))); //let material_center = Arc::new(Dielectric::new(1.5)); - let material_blue = Arc::new(Lambertian::new(&Color::new(0.2, 0.1, 0.7))); - let material_metal = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.1)); - let material_metal_fuzz = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 1.0)); - let material_mirror = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.0)); - let material_dielectric = Arc::new(Dielectric::new(1.5)); - let material_light = Arc::new(Lambertian::new(&Color::new(2.0, 1.0, 0.0))); + //let material_blue = Arc::new(Lambertian::new(&Color::new(0.2, 0.1, 0.7))); + //let material_metal = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.1)); + //let material_metal_fuzz = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 1.0)); + //let material_mirror = Arc::new(Metal::new(&Color::new(0.8, 0.8, 0.8), 0.0)); + //let material_dielectric = Arc::new(Dielectric::new(1.5)); + //let material_light = Arc::new(Lambertian::new(&Color::new(2.0, 1.0, 0.0))); + world.add(Box::::new(Sphere::new( - Point3::new(0.0, -100.5, -1.0), - 100.0, + Point3::new(0.0, -1000.0, 0.0), + 1000.0, material_ground.clone(), ))); + + (-6..5).into_iter().for_each(|a| { + (-6..5).into_iter().for_each(|b| { + let choose_mat = utility::random_f64(); + let center = Point3::new(a as f64 + 0.9 * utility::random_f64(), 0.2, b as f64 + 0.9 * utility::random_f64()); + if (center - Point3::new(4.0, 0.2, 0.0)).length() > 0.9 { + if choose_mat < 0.8 { // diffuse + let sphere_material = Arc::new(Lambertian::new(&(Color::random_f64() * Color::random_f64()))); + world.add(Box::::new(Sphere::new( + center, + 0.2, + sphere_material.clone() + ))); + } else if choose_mat < 0.95 { // metal + let sphere_material = Arc::new(Metal::new(&Color::random_rng(0.5, 1.0), utility::random_rng(0.0, 0.5))); + world.add(Box::::new(Sphere::new( + center, + 0.2, + sphere_material.clone() + ))); + } else { // glass + let sphere_material = Arc::new(Dielectric::new(1.5)); + world.add(Box::::new(Sphere::new( + center, + 0.2, + sphere_material.clone() + ))); + } + + } + }); + }); + + let material1 = Arc::new(Dielectric::new(1.5)); + let material3 = Arc::new(Metal::new(&Color::new(0.7, 0.6, 0.5), 0.0)); + let material2 = Arc::new(Lambertian::new(&Color::new(0.4, 0.2, 0.1))); + world.add(Box::::new(Sphere::new( - Point3::new(0.0, 0.0, -1.0), - 0.5, - material_center.clone(), + Point3::new(0.0, 1.0, 0.0), + 1.0, + material2.clone(), ))); + world.add(Box::::new(Sphere::new( - Point3::new(-1.0, -0.15, -1.0), - 0.5, + Point3::new(-4.0, 1.0, 0.0), + 1.0, + material1.clone(), + ))); + + world.add(Box::::new(Sphere::new( + Point3::new(4.0, 1.0, 0.0), + 1.0, + material3.clone(), + ))); + + /* + world.add(Box::::new(Sphere::new( + Point3::new(-2.0*r, 0.1, -2.0), + r, material_dielectric.clone(), ))); world.add(Box::::new(Sphere::new( - Point3::new(1.0, 0.0, -1.0), - -0.4, + Point3::new(r, 0.0, -1.0), + r, material_dielectric.clone(), ))); world.add(Box::::new(Sphere::new( @@ -97,7 +139,7 @@ fn main() { ))); world.add(Box::::new(Sphere::new( Point3::new(-0.5, 0.5, 1.0), - 1.0, + 0.4, material_blue.clone(), ))); world.add(Box::::new(Sphere::new( @@ -105,6 +147,8 @@ fn main() { 0.3, material_light.clone(), ))); + */ + /* for i in -15..15 { for j in -15..15 { @@ -113,8 +157,32 @@ fn main() { } */ + return world; +} + +fn main() { + // File + let mut default_file = "image.ppm"; + + // Image + let aspect_ratio = 16.0 / 9.0; + let image_width = 1920; + let image_height = (image_width as f64 / aspect_ratio) as u32; + let samples_per_pixel = 100_u32; + let max_depth = 50; + + let vfov = 20.0; + let lookfrom = Point3::new(10.0, 10.0, 13.0); + let lookat = Point3::new(0.0, 0.0, 0.0); + let vup = Vec3::new(0.0, 1.0, 0.0); + let dist_to_focus = 15.0; + let aperture = 0.1; + + // World + let world = random_world(); + // Camera - let cam = Camera::new(); + let cam = Camera::new(lookfrom, lookat, vup, vfov, aspect_ratio, aperture, dist_to_focus); // Render let args: Vec = env::args().collect(); diff --git a/src/utility.rs b/src/utility.rs index ff0f6ee..4532c9f 100644 --- a/src/utility.rs +++ b/src/utility.rs @@ -22,4 +22,4 @@ pub fn clamp(x: f64, min: f64, max: f64) -> f64 { return max; } return x; -} +} \ No newline at end of file diff --git a/src/vec3.rs b/src/vec3.rs index 01a1945..aec711c 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -83,7 +83,17 @@ impl Vec3 { let p = Vec3::random_rng(-1.0, 1.0); if p.length_squared() >= 1.0 { continue; - }; + } + return p; + } + } + + pub fn random_in_unit_disk() -> Self { + loop { + let p = Vec3::new(utility::random_rng(-1.0, 1.0), utility::random_rng(-1.0, 1.0), 0.0); + if p.length_squared() >= 1.0 { + continue; + } return p; } }