Compare commits

...

2 Commits

Author SHA1 Message Date
dengqn ff4132edff Merge branch 'master' of https://git.dengqn.com/dqn/ray-trace-w1 2025-08-19 08:33:43 +08:00
dengqn 06c5528599 14.1 A Final Render 2025-08-19 08:33:05 +08:00
2 changed files with 61 additions and 27 deletions

View File

@ -1,6 +1,8 @@
use std::fs::File; use std::fs::File;
use std::io::BufWriter; use std::io::BufWriter;
use rand::{rng, Rng};
use crate::hittable::HittableList; use crate::hittable::HittableList;
use crate::material::{Dielectric, Lambertian, MaterialKind, Metal}; use crate::material::{Dielectric, Lambertian, MaterialKind, Metal};
use crate::ppm_writer::PPMWriter; use crate::ppm_writer::PPMWriter;
@ -22,12 +24,12 @@ fn main() {
fn camera_render() { fn camera_render() {
let fov: f32 = 60.; let fov: f32 = 90.;
let scale = 2; let scale = 1;
let width: i32 = 800/scale; let width: i32 = 1920/scale;
let height: i32 = 600/scale; let height: i32 = 1080/scale;
let sample_times = 20; let sample_times = 50;
let reflect_depth = 20; let reflect_depth = 64;
let pw_r = PPMWriter::new( let pw_r = PPMWriter::new(
@ -44,7 +46,7 @@ fn camera_render() {
fov, fov,
width, width,
width as f32 / height as f32, width as f32 / height as f32,
Point::new(-0.0, 0.0, 0.0), Point::new(-0.0, 5.0, 5.0),
Point::new(0.0, 0.0, -1.0), Point::new(0.0, 0.0, -1.0),
Vec3::new(0., 1., 0.), Vec3::new(0., 1., 0.),
sample_times, sample_times,
@ -57,23 +59,60 @@ fn camera_render() {
// world objects(spheres) // world objects(spheres)
let mut world = HittableList::new(); let mut world = HittableList::new();
let plane_m = Some(MaterialKind::Lambertian(Lambertian{albedo: Color::new(0.899, 0.899, 0.999)})); 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 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 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_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 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})); // let right_m = Some(MaterialKind::Metal(Metal{albedo: Color::new(0.8, 0.6, 0.2), fuzz: 0.003}));
// 折射率 1.33 // // 折射率 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_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 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(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.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.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(-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(-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(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))); 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); 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))));
}
}

View File

@ -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 { 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); *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(); let unit_direction = r_in.direction.normalize();