diff --git a/ria-weekend/Cargo.lock b/ria-weekend/Cargo.lock index 854f3fb..c2f7a31 100644 --- a/ria-weekend/Cargo.lock +++ b/ria-weekend/Cargo.lock @@ -1,251 +1,128 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "autocfg" -version = "0.1.2" +name = "bitflags" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] -name = "bitflags" -version = "1.0.4" +name = "c2-chacha" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.50" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" [[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" +name = "ppv-lite86" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "rand" -version = "0.6.5" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha", + "rand_core", ] [[package]] name = "rand_core" -version = "0.3.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rand_hc" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core", ] [[package]] name = "ria-weekend" version = "0.1.0" dependencies = [ - "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", + "sdl2", ] [[package]] name = "sdl2" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f74124048ea86b5cd50236b2443f6f57cf4625a8e8818009b4e50dbb8729a43" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "lazy_static", + "libc", + "sdl2-sys", ] [[package]] name = "sdl2-sys" -version = "0.32.5" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e1deb61ff274d29fb985017d4611d4004b113676eaa9c06754194caf82094e" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", ] [[package]] -name = "winapi" -version = "0.3.6" +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebf85f207d42e4da59fa31fff977be5ff0b224873506c4bd70cc1c94b331593" -"checksum sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e82803e85c2e6178d28886cef25b2c53afc2eecaeff739f2247f23ed3352e6c1" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" diff --git a/ria-weekend/Cargo.toml b/ria-weekend/Cargo.toml index 91ec00e..5580030 100644 --- a/ria-weekend/Cargo.toml +++ b/ria-weekend/Cargo.toml @@ -6,3 +6,4 @@ edition = "2018" [dependencies] sdl2 = "*" +rand = "*" diff --git a/ria-weekend/src/camera.rs b/ria-weekend/src/camera.rs new file mode 100644 index 0000000..6452785 --- /dev/null +++ b/ria-weekend/src/camera.rs @@ -0,0 +1,38 @@ +use crate::types::{Ray, Vec3}; + +#[derive(Debug)] +pub struct Camera { + origin: Vec3, + vertical: Vec3, + horizontal: Vec3, + lower_left_corner: Vec3, +} + +impl Camera { + pub fn new(origin: Vec3, vertical: Vec3, horizontal: Vec3, lower_left_corner: Vec3) -> Camera { + Camera { + origin, + vertical, + horizontal, + lower_left_corner, + } + } + + pub fn get_ray(&self, u: f32, v: f32) -> Ray { + Ray::new( + self.origin, + self.lower_left_corner + self.horizontal * u + self.vertical * v, + ) + } +} + +impl Default for Camera { + fn default() -> Camera { + Camera { + origin: Vec3::new(0.0, 0.0, 0.0), + vertical: Vec3::new(0.0, 2.0, 0.0), + horizontal: Vec3::new(4.0, 0.0, 0.0), + lower_left_corner: Vec3::new(-2.0, -1.0, -1.0), + } + } +} diff --git a/ria-weekend/src/demo.rs b/ria-weekend/src/demo.rs index 7641057..ca4f2f8 100644 --- a/ria-weekend/src/demo.rs +++ b/ria-weekend/src/demo.rs @@ -3,7 +3,7 @@ use std::fs::File; use std::io::Write; pub trait Demo { - fn render(&self, buf: &mut Vec, width: usize, height: usize); + fn render(&self, buf: &mut Vec, width: usize, height: usize, samples: u8); fn name(&self) -> String; fn save_as_ppm(&self, buf: &[u8], width: usize, height: usize) { diff --git a/ria-weekend/src/demos/antialiasing.rs b/ria-weekend/src/demos/antialiasing.rs new file mode 100644 index 0000000..f4e7c80 --- /dev/null +++ b/ria-weekend/src/demos/antialiasing.rs @@ -0,0 +1,42 @@ +use crate::camera::Camera; +use crate::hitable::{HitRecord, Hitable, HitableList}; +use crate::shapes; +use crate::types::{Ray, Vec3}; +use rand::Rng; + +pub struct Antialiasing; + +impl crate::Demo for Antialiasing { + fn name(&self) -> String { + "antialiasing".to_owned() + } + + fn render(&self, buf: &mut Vec, w: usize, h: usize, ns: u8) { + let list: Vec> = vec![ + Box::new(shapes::Sphere::new(Vec3::new(0.0, 0.0, -1.0), 0.5)), + Box::new(shapes::Sphere::new(Vec3::new(0.0, -100.5, -1.0), 100.0)), + ]; + let world = HitableList::new(list); + let camera = Camera::default(); + let mut rng = rand::thread_rng(); + } +} + +fn calculate_color(ray: Ray, world: &HitableList) -> Vec3 { + let mut hit_rec = HitRecord { + t: 0.0, + normal: Vec3::new(0.0, 0.0, 0.0), + point: Vec3::new(0.0, 0.0, 0.0), + }; + if world.hit(&ray, 0.001, std::f32::MAX, &mut hit_rec) { + Vec3::new( + hit_rec.normal.x() + 1.0, + hit_rec.normal.y() + 1.0, + hit_rec.normal.z() + 1.0, + ) * 0.5 + } else { + let unit_direction = ray.direction().unit_vector(); + let t = 0.5 * (unit_direction.y() + 1.0); + Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t + } +} diff --git a/ria-weekend/src/demos/hitable_surface_normal_sphere.rs b/ria-weekend/src/demos/hitable_surface_normal_sphere.rs index f434050..0f7891d 100644 --- a/ria-weekend/src/demos/hitable_surface_normal_sphere.rs +++ b/ria-weekend/src/demos/hitable_surface_normal_sphere.rs @@ -1,8 +1,7 @@ use crate::{ hitable::{HitRecord, Hitable, HitableList}, - ray::Ray, shapes, - vec3::Vec3, + types::{Ray, Vec3}, }; const RADIUS: f32 = 0.5; @@ -13,7 +12,7 @@ impl crate::Demo for HitableSurfaceNormalSphere { "hit-table_surface_normal_sphere".to_owned() } - fn render(&self, buf: &mut Vec, w: usize, h: usize) { + fn render(&self, buf: &mut Vec, w: usize, h: usize, _ns: u8) { // in my case, The resolution is 1200x800 // These numbers are calculated by first calculating the aspect ratio // and then just figuring out lower left corner, Width(2 x aspect ratio width) diff --git a/ria-weekend/src/demos/linear_interpolation_y.rs b/ria-weekend/src/demos/linear_interpolation_y.rs deleted file mode 100644 index ca7d82a..0000000 --- a/ria-weekend/src/demos/linear_interpolation_y.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::ray::Ray; -use crate::vec3::Vec3; - -pub struct LinearInterpolationY; - -impl crate::Demo for LinearInterpolationY { - fn name(&self) -> String { - "linear_interpolation_y".to_owned() - } - - fn render(&self, buf: &mut Vec, w: usize, h: usize) { - // in my case, The resolution is 1200x800 - // These numbers are calculated by first calculating the aspect ratio - // and then just figuring out lower left corner, Width(2 x aspect ratio width) - // Height(2 x aspect ratio height) - let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0); - let horizontal = Vec3::new(4.0, 0.0, 0.0); - let vertical = Vec3::new(0.0, 2.0, 0.0); - // Observer position - let origin = Vec3::new(0.0, 0.0, 0.0); - - let mut offset = 0; - for j in (0..h).rev() { - for i in 0..w { - // relative offsets - // current position to total width/length - let u = i as f32 / w as f32; - let v = j as f32 / h as f32; - - let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); - let color = calc_color(ray); - let ir = (255.99 * color.r()) as u8; - let ig = (255.99 * color.g()) as u8; - let ib = (255.99 * color.b()) as u8; - - buf[offset] = ir; - buf[offset + 1] = ig; - buf[offset + 2] = ib; - offset += 4; - } - } - } -} - -#[inline] -fn calc_color(ray: Ray) -> Vec3 { - let unit_direction = ray.direction().unit_vector(); - let t = 0.5 * (unit_direction.y() + 1.0); - // (1.0 - t) * start blend_color + t * end color - Vec3::new(1.0, 1.0, 1.0) * (1.0 - t) + Vec3::new(0.5, 0.7, 1.0) * t -} diff --git a/ria-weekend/src/demos/mod.rs b/ria-weekend/src/demos/mod.rs index 45defc3..e945c6e 100644 --- a/ria-weekend/src/demos/mod.rs +++ b/ria-weekend/src/demos/mod.rs @@ -1,11 +1,9 @@ +mod antialiasing; mod hitable_surface_normal_sphere; -mod linear_interpolation_y; -mod ppm_example; mod simple_sphere; mod surface_normal_sphere; +pub use antialiasing::Antialiasing; pub use hitable_surface_normal_sphere::HitableSurfaceNormalSphere; -pub use linear_interpolation_y::LinearInterpolationY; -pub use ppm_example::PpmExample; pub use simple_sphere::SimpleSphere; pub use surface_normal_sphere::SurfaceNormalSphere; diff --git a/ria-weekend/src/demos/ppm_example.rs b/ria-weekend/src/demos/ppm_example.rs deleted file mode 100644 index fc2d4e2..0000000 --- a/ria-weekend/src/demos/ppm_example.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::vec3::Vec3; -pub struct PpmExample; - -impl crate::Demo for PpmExample { - fn name(&self) -> String { - "ppm_example".to_owned() - } - - fn render(&self, buf: &mut Vec, w: usize, h: usize) { - let mut offset = 0; - for j in (0..h).rev() { - for i in 0..w { - let color = Vec3::new((i as f32) / (w as f32), (j as f32) / (h as f32), 0.2); - - let ir = (255.99 * color.r()) as u8; - let ig = (255.99 * color.g()) as u8; - let ib = (255.99 * color.b()) as u8; - - buf[offset] = ir; - buf[offset + 1] = ig; - buf[offset + 2] = ib; - - offset += 4; - } - } - } -} diff --git a/ria-weekend/src/demos/simple_sphere.rs b/ria-weekend/src/demos/simple_sphere.rs index e3ac9c2..cade118 100644 --- a/ria-weekend/src/demos/simple_sphere.rs +++ b/ria-weekend/src/demos/simple_sphere.rs @@ -1,4 +1,4 @@ -use crate::{ray::Ray, vec3::Vec3}; +use crate::types::{Ray, Vec3}; const RADIUS: f32 = 0.5; @@ -9,7 +9,7 @@ impl crate::Demo for SimpleSphere { "simple_sphere".to_owned() } - fn render(&self, buf: &mut Vec, w: usize, h: usize) { + fn render(&self, buf: &mut Vec, w: usize, h: usize, _ns: u8) { // in my case, The resolution is 1200x800 // These numbers are calculated by first calculating the aspect ratio // and then just figuring out lower left corner, Width(2 x aspect ratio width) diff --git a/ria-weekend/src/demos/surface_normal_sphere.rs b/ria-weekend/src/demos/surface_normal_sphere.rs index 6fa0654..d7aabdb 100644 --- a/ria-weekend/src/demos/surface_normal_sphere.rs +++ b/ria-weekend/src/demos/surface_normal_sphere.rs @@ -1,4 +1,4 @@ -use crate::{ray::Ray, vec3::Vec3}; +use crate::types::{Ray, Vec3}; const RADIUS: f32 = 0.5; pub struct SurfaceNormalSphere; @@ -8,7 +8,7 @@ impl crate::Demo for SurfaceNormalSphere { "surface_normal_sphere".to_owned() } - fn render(&self, buf: &mut Vec, w: usize, h: usize) { + fn render(&self, buf: &mut Vec, w: usize, h: usize, _ns: u8) { // in my case, The resolution is 1200x800 // These numbers are calculated by first calculating the aspect ratio // and then just figuring out lower left corner, Width(2 x aspect ratio width) diff --git a/ria-weekend/src/hitable.rs b/ria-weekend/src/hitable.rs index 753b744..59fd7e5 100644 --- a/ria-weekend/src/hitable.rs +++ b/ria-weekend/src/hitable.rs @@ -1,5 +1,4 @@ -use crate::ray::Ray; -use crate::vec3::Vec3; +use crate::types::{Ray, Vec3}; #[derive(Debug, Copy, Clone)] pub struct HitRecord { diff --git a/ria-weekend/src/main.rs b/ria-weekend/src/main.rs index 93ec344..30348ca 100644 --- a/ria-weekend/src/main.rs +++ b/ria-weekend/src/main.rs @@ -1,20 +1,22 @@ +#![feature(impl_trait_in_bindings)] + +mod camera; mod demo; mod demos; mod hitable; -mod ray; +mod render; mod shapes; -mod vec3; +mod types; use demo::Demo; -use demos::{ - HitableSurfaceNormalSphere, LinearInterpolationY, PpmExample, SimpleSphere, SurfaceNormalSphere, -}; use sdl2::{ event::{Event, WindowEvent}, keyboard::Keycode, pixels::PixelFormatEnum, }; +const NUM_SAMPLES: u8 = 10; + fn main() -> Result<(), String> { let sdl_ctx = sdl2::init()?; let video_subsys = sdl_ctx.video()?; @@ -43,10 +45,9 @@ fn main() -> Result<(), String> { .create_texture_static(PixelFormatEnum::BGR888, width as u32, height as u32) .map_err(|e| e.to_string())?; - let mut active_demo: Box = Box::new(PpmExample); - //println!("{:?} {:?} {:?}", texture.query(), texture.color_mod(), texture.alpha_mod()); + let active_demo: impl Demo = demos::SurfaceNormalSphere; // TODO: Should update when window is unfocus since the project window retains // data from overlapped window // TODO: Maybe consider using condition variable to make loop {} not run at full @@ -60,41 +61,6 @@ fn main() -> Result<(), String> { keycode: Some(Keycode::Escape), .. } => return Ok(()), - Event::KeyUp { - keycode: Some(Keycode::Num1), - .. - } => { - should_update = true; - active_demo = Box::new(PpmExample); - } - Event::KeyUp { - keycode: Some(Keycode::Num2), - .. - } => { - should_update = true; - active_demo = Box::new(LinearInterpolationY); - } - Event::KeyUp { - keycode: Some(Keycode::Num3), - .. - } => { - should_update = true; - active_demo = Box::new(SimpleSphere); - } - Event::KeyUp { - keycode: Some(Keycode::Num4), - .. - } => { - should_update = true; - active_demo = Box::new(SurfaceNormalSphere); - } - Event::KeyUp { - keycode: Some(Keycode::Num5), - .. - } => { - should_update = true; - active_demo = Box::new(HitableSurfaceNormalSphere); - } Event::KeyUp { keycode: Some(Keycode::S), .. @@ -115,7 +81,7 @@ fn main() -> Result<(), String> { }; } if should_update { - active_demo.render(&mut buffer, width, height); + active_demo.render(&mut buffer, width, height, NUM_SAMPLES); texture.update(None, &buffer, width * 4); canvas.copy(&texture, None, None); canvas.present(); diff --git a/ria-weekend/src/render.rs b/ria-weekend/src/render.rs new file mode 100644 index 0000000..ed86306 --- /dev/null +++ b/ria-weekend/src/render.rs @@ -0,0 +1,75 @@ +use crate::hitable::{HitRecord, Hitable, HitableList}; +use crate::shapes; +use crate::types::{Ray, Vec3}; +use rand::Rng; +use std::error::Error; +use std::fs::File; +use std::io::Write; + +pub struct Renderer { + width: usize, + height: usize, +} + +impl Renderer { + fn new(width: usize, height: usize) -> Renderer { + Renderer { width, height } + } + + fn update_dimensions(&mut self, width: usize, height: usize) {} + + fn render(&mut self, buf: &mut Vec, world: &HitableList, calc_color: F) + where + F: Fn(Ray, &HitableList) -> Vec3, + { + let w = self.width; + let h = self.height; + // in my case, The resolution is 1200x800 + // These numbers are calculated by first calculating the aspect ratio + // and then just figuring out lower left corner, Width(2 x aspect ratio width) + // Height(2 x aspect ratio height) + let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0); + let horizontal = Vec3::new(4.0, 0.0, 0.0); + let vertical = Vec3::new(0.0, 2.0, 0.0); + let origin = Vec3::new(0.0, 0.0, 0.0); + + let mut offset = 0; + for j in (0..h).rev() { + for i in 0..w { + let u = i as f32 / w as f32; + let v = j as f32 / h as f32; + + let ray = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v); + + let color = calc_color(ray, &world); + let ir = (255.99 * color.r()) as u8; + let ig = (255.99 * color.g()) as u8; + let ib = (255.99 * color.b()) as u8; + + buf[offset] = ir; + buf[offset + 1] = ig; + buf[offset + 2] = ib; + offset += 4; + } + } + } + + fn save_as_ppm(&self, buf: &[u8], name: &str) { + let (width, height) = (self.width, self.height); + let header = format!("P3\n{} {}\n255\n", width, height); + + let mut file = match File::create(&format!("{}-{}x{}.ppm", name, width, height)) { + Ok(file) => file, + Err(e) => panic!("couldn't create {}: {}", name, e), + }; + file.write(header.as_bytes()) + .expect("error in writing file header"); + + for i in buf.chunks(4) { + match file.write(format!("{} {} {}\n", i[0], i[1], i[2]).as_bytes()) { + Ok(_) => (), + Err(e) => panic!("couldn't write to {}: {}", name, e), + } + } + } +} diff --git a/ria-weekend/src/shapes/sphere.rs b/ria-weekend/src/shapes/sphere.rs index 96609d2..b0995d5 100644 --- a/ria-weekend/src/shapes/sphere.rs +++ b/ria-weekend/src/shapes/sphere.rs @@ -1,7 +1,6 @@ use crate::{ hitable::{HitRecord, Hitable}, - ray::Ray, - vec3::Vec3, + types::{Ray, Vec3}, }; pub struct Sphere { diff --git a/ria-weekend/src/types/mod.rs b/ria-weekend/src/types/mod.rs new file mode 100644 index 0000000..d5dd4ac --- /dev/null +++ b/ria-weekend/src/types/mod.rs @@ -0,0 +1,5 @@ +mod ray; +mod vec3; + +pub use ray::Ray; +pub use vec3::Vec3; diff --git a/ria-weekend/src/ray.rs b/ria-weekend/src/types/ray.rs similarity index 94% rename from ria-weekend/src/ray.rs rename to ria-weekend/src/types/ray.rs index 6b03b3f..d26221d 100644 --- a/ria-weekend/src/ray.rs +++ b/ria-weekend/src/types/ray.rs @@ -1,4 +1,4 @@ -use crate::vec3::Vec3; +use crate::types::Vec3; #[derive(Debug)] pub struct Ray { diff --git a/ria-weekend/src/vec3.rs b/ria-weekend/src/types/vec3.rs similarity index 86% rename from ria-weekend/src/vec3.rs rename to ria-weekend/src/types/vec3.rs index 84bd731..99d926d 100644 --- a/ria-weekend/src/vec3.rs +++ b/ria-weekend/src/types/vec3.rs @@ -1,4 +1,4 @@ -use std::ops::{Add, Div, Index, IndexMut, Mul, MulAssign, Sub}; +use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub}; #[derive(Debug, Copy, Clone)] pub struct Vec3 { @@ -79,6 +79,14 @@ impl Add for Vec3 { } } +impl AddAssign for Vec3 { + fn add_assign(&mut self, o: Vec3) { + self.inner[0] += o.inner[0]; + self.inner[1] += o.inner[1]; + self.inner[2] += o.inner[2]; + } +} + impl Sub for Vec3 { type Output = Vec3; @@ -135,6 +143,15 @@ impl Div for Vec3 { } } +impl DivAssign for Vec3 { + fn div_assign(&mut self, o: f32) { + let o = 1.0 / o; + self.inner[0] /= o; + self.inner[1] /= o; + self.inner[2] /= o; + } +} + impl Index for Vec3 { type Output = f32;