diff --git a/src/main.rs b/src/main.rs index d751b23..23c2097 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ use std::fs::File; use std::io::BufWriter; +use rand::{rng, Rng}; + use crate::hittable::HittableList; use crate::material::{Dielectric, Lambertian, MaterialKind, Metal}; use crate::ppm_writer::PPMWriter; @@ -22,12 +24,12 @@ fn main() { fn camera_render() { - let fov: f32 = 60.; + let fov: f32 = 90.; let scale = 1; - let width: i32 = 800/scale; - let height: i32 = 600/scale; + let width: i32 = 1920/scale; + let height: i32 = 1080/scale; let sample_times = 50; - let reflect_depth = 20; + let reflect_depth = 64; let pw_r = PPMWriter::new( @@ -44,7 +46,7 @@ fn camera_render() { fov, width, width as f32 / height as f32, - Point::new(-2.0, 0.0, -1.0), + Point::new(-0.0, 5.0, 5.0), Point::new(0.0, 0.0, -1.0), Vec3::new(0., 1., 0.), sample_times, @@ -55,23 +57,60 @@ fn camera_render() { // world objects(spheres) let mut world = HittableList::new(); - let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.899, 0.899, 0.999)})); - // let plane2_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.784,0.784,0.784)})); - let center_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.2, 0.5, 0.5)})); - let left_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.799, 0.599, 0.799), fuzz: 0.0005})); - let left_behind_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.799, 0.599, 0.599)})); - let right_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.8, 0.6, 0.2), fuzz: 0.003})); - // 折射率 1.33 - let left_dia_m = Some(MaterialKind::Dielectric(Dielectric{albedo: Color::new(0.8, 0.6, 0.2), refraction_index: 1.00 / 1.33})); - let left_dia_small_m = Some(MaterialKind::Dielectric(Dielectric{albedo: Color::new(0.8, 0.6, 0.2), refraction_index: 1.00 / 2.5})); + let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.508, 0.508, 0.508)})); + // // let plane2_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.784,0.784,0.784)})); + // let center_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.2, 0.5, 0.5)})); + // let left_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.799, 0.599, 0.799), fuzz: 0.0005})); + // let left_behind_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.799, 0.599, 0.599)})); + // let right_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.8, 0.6, 0.2), fuzz: 0.003})); + // // 折射率 1.33 + // let left_dia_m = Some(MaterialKind::Dielectric(Dielectric{albedo: Color::new(0.8, 0.6, 0.2), refraction_index: 1.00 / 1.33})); + // let left_dia_small_m = Some(MaterialKind::Dielectric(Dielectric{albedo: Color::new(0.8, 0.6, 0.2), refraction_index: 1.00 / 2.5})); - world.put(Box::new(Sphere::new(Point::new(0.0, 0.0, -1.0), 0.5, center_m))); - world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.5, left_dia_m))); - world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.2, left_dia_small_m))); - // world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.5, left_m))); - world.put(Box::new(Sphere::new(Point::new(-3.5, 1.5, -5.5), 1.5, left_behind_m))); - world.put(Box::new(Sphere::new(Point::new(1.0, 0.0, -1.0), 0.5, right_m))); + // world.put(Box::new(Sphere::new(Point::new(0.0, 0.0, -1.0), 0.5, center_m))); + // world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.5, left_dia_m))); + // world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.2, left_dia_small_m))); + // // world.put(Box::new(Sphere::new(Point::new(-1.0, 0.0, -1.0), 0.5, left_m))); + // world.put(Box::new(Sphere::new(Point::new(-3.5, 1.5, -5.5), 1.5, left_behind_m))); + // world.put(Box::new(Sphere::new(Point::new(1.0, 0.0, -1.0), 0.5, right_m))); world.put(Box::new(Sphere::new(Point::new(0.0, -500.5, -1.0), 500.0, plane_m))); + gen_spheres(&mut world); + camera.render(&world); } + + +fn gen_spheres(world: &mut HittableList) { + let rng = &mut rng(); + + for _ in 0..500 { + let x = rng.random_range(-20..20); + let z = rng.random_range(-20..20); + + let radius = rng.random_range(0.01..0.8); + + // R = random(0.7, 0.95) # 红通道 + // G = random(R - 0.2, R + 0.2) # 绿通道(与 R 相近) + // B = random(min(R, G) - 0.15, max(R, G) + 0.15) # 蓝通道(与 R/G 相近) + // 基础值在 0.7~0.95 之间 + let base:f32 = rng.random_range(0.7..0.95); + // 每个通道在 base 附近小幅波动(±0.15) + let r: f32 = rng.random_range((base - 0.15).max(0.6)..(base + 0.15).min(1.0)); + let g: f32 = rng.random_range((base - 0.15).max(0.6)..(base + 0.15).min(1.0)); + let b: f32 = rng.random_range((base - 0.15).max(0.6)..(base + 0.15).min(1.0)); + + let materail_color = Color::new(r,g, b); + + let materail_kind = rng.random_range(0.0..1.0); + let material = if materail_kind <= 0.33333 { + MaterialKind::Lambertian(Lambertian { albedo: materail_color }) + } else if materail_kind > 0.3 && materail_kind <= 0.66666 { + MaterialKind::Metal(Metal { albedo: materail_color, fuzz: 0.00001 }) + } else { + MaterialKind::Dielectric(Dielectric { albedo: materail_color, refraction_index: 1./1.5 }) + }; + + world.put(Box::new(Sphere::new(Point::new(x as f32, 0., z as f32), radius, Some(material)))); + } +} \ No newline at end of file diff --git a/src/material.rs b/src/material.rs index a2d7b40..2627753 100644 --- a/src/material.rs +++ b/src/material.rs @@ -87,11 +87,6 @@ impl Material for Dielectric { fn scatter(&self, r_in: &Ray, hit_record: &mut HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { *attenuation = Color::new(1.0, 1.0, 1.0); - let ri = if hit_record.front_face { - 1.0 / self.refraction_index - } else { - self.refraction_index - }; let unit_direction = r_in.direction.normalize();