14.1 A Final Render
This commit is contained in:
parent
caa21505ba
commit
06c5528599
79
src/main.rs
79
src/main.rs
|
@ -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 = 1;
|
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 = 50;
|
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(-2.0, 0.0, -1.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,
|
||||||
|
@ -55,23 +57,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))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue