diff --git a/Cargo.lock b/Cargo.lock index 285b107..65e2074 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,132 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "ray-trace-w1" version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 8ab0327..29ab145 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +rand = "0.8.5" # 使用最新稳定版 \ No newline at end of file diff --git a/src/camera.rs b/src/camera.rs index f54d38e..904d12c 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,5 +1,8 @@ use crate::hittable::HittableList; +use crate::math_utils::clamp; use crate::types_defined::{Camera, Color, Point, Ray, Vec3}; +use rand::rngs::ThreadRng; +use rand::{Rng, thread_rng}; impl Camera { pub fn new( @@ -8,6 +11,7 @@ impl Camera { viewport_height: f32, camera_center: Point, focal_length: Vec3, + sample_times: i8, ) -> Self { let image_height = ((image_width as f32 / aspect_ratio) as i32).max(1); let viewport_width = viewport_height * (image_width as f32 / image_height as f32); @@ -41,6 +45,7 @@ impl Camera { viewport_u_delta, viewport_v_delta, viewport_top_left_pixel_center, + sample_times: sample_times, } } @@ -53,18 +58,30 @@ impl Camera { } for i in 0..self.image_width { - // every pixcel's position - let pixel_center = self.viewport_top_left_pixel_center - + (i as f32 * self.viewport_u_delta) - + (j as f32 * self.viewport_v_delta); - // Vector(camera, pixcel) - let ray_direction = pixel_center - self.camera_center; - // ray - let r = Ray::new(self.camera_center, ray_direction); - // determind color - let color = self.ray_color(&r, world); + // color + let mut color = Color::new(0.0, 0.0, 0.0); + let rng = &mut thread_rng(); + for s in 0..self.sample_times { + let bias = self.random_square(rng); + let pix_sample = self.viewport_top_left_pixel_center + + (i as f32 + bias.x) * self.viewport_u_delta + + (j as f32 + bias.y) * self.viewport_v_delta; + let r = Ray::new(self.camera_center, pix_sample - self.camera_center); + let sample_color = self.ray_color(&r, world); + color = color + sample_color; + } + // color * each sample color + color = color * (1.0 / self.sample_times as f32); + + // clamp color rgb + let color_clamped = Color::new( + clamp(color.x, 0.0, 1.0), + clamp(color.y, 0.0, 1.0), + clamp(color.z, 0.0, 1.0), + ); + // content - img_content.push_str(color.to_color().as_str()); + img_content.push_str(color_clamped.to_color().as_str()); img_content.push('\n'); } } @@ -88,4 +105,9 @@ impl Camera { // return background color. (1.0 - a) * Color::new(1.0, 1.0, 1.0) + a * Color::new(0.5, 0.7, 1.0) } + + // -> [x, y, 0] + fn random_square(&self, rng: &mut ThreadRng) -> Vec3 { + Vec3::new(rng.gen_range(-0.5..0.1), rng.gen_range(-0.5..0.1), 0.0) + } } diff --git a/src/main.rs b/src/main.rs index f319a14..9451879 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod sphere; mod types_defined; mod vec3; mod write_file_util; +mod math_utils; fn main() { camera_render(); @@ -16,11 +17,12 @@ fn main() { fn camera_render() { let camera = Camera::new( - 800, + 400, 16.0 / 9.0, 2.0, Point::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, -1.0), + 10 ); // world // world objects(spheres) diff --git a/src/math_utils.rs b/src/math_utils.rs new file mode 100644 index 0000000..56a60cf --- /dev/null +++ b/src/math_utils.rs @@ -0,0 +1,10 @@ + +pub fn clamp(value: f32, low: f32, high: f32) -> f32 { + if value < low { + return low; + } + if value > high { + return high; + } + return value; +} \ No newline at end of file diff --git a/src/types_defined.rs b/src/types_defined.rs index a4ee75b..4b5a4c6 100644 --- a/src/types_defined.rs +++ b/src/types_defined.rs @@ -41,6 +41,9 @@ pub struct Camera { pub viewport_u_delta: Vec3, pub viewport_v_delta: Vec3, pub viewport_top_left_pixel_center: Vec3, + + // sample times + pub sample_times: i8 } /*