環境
- Time 2022-11-17
- WSL-Ubuntu 22.04
- Rust 1.65.0
前言
說明
參考:https://raytracing.github.io/books/RayTracingInOneWeekend.html
目標
將之前的所有的內容合併在一起生成一個最終的影像。
vector3.rs
pub fn random(range: Range<f64>) -> Vector3 {
let mut rng = rand::thread_rng();
Vector3 {
x: rng.gen_range(range.clone()),
y: rng.gen_range(range.clone()),
z: rng.gen_range(range),
}
}
生成場景
fn random_scene() -> World {
let mut rng = rand::thread_rng();
let mut world = World::new();
let ground = Rc::new(Lambert::new(Color::new(0.5, 0.5, 0.5)));
let ground = Sphere::new(Point3::new(0.0, -1000.0, 0.0), 1000.0, ground);
world.push(Box::new(ground));
for a in -11..=11 {
for b in -11..=11 {
let choose_mat: f64 = rng.gen();
let center = Point3::new(
(a as f64) + rng.gen_range(0.0..0.9),
0.2,
(b as f64) + rng.gen_range(0.0..0.9),
);
if choose_mat < 0.8 {
let albedo = Color::random(0.0..1.0) * Color::random(0.0..1.0);
let sphere_mat = Rc::new(Lambert::new(albedo));
let sphere = Sphere::new(center, 0.2, sphere_mat);
world.push(Box::new(sphere));
} else if choose_mat < 0.95 {
let albedo = Color::random(0.4..1.0);
let fuzz = rng.gen_range(0.0..0.5);
let sphere_mat = Rc::new(Metal::new(albedo, fuzz));
let sphere = Sphere::new(center, 0.2, sphere_mat);
world.push(Box::new(sphere));
} else {
// Glass
let sphere_mat = Rc::new(Dielectric::new(1.5));
let sphere = Sphere::new(center, 0.2, sphere_mat);
world.push(Box::new(sphere));
}
}
}
let mat1 = Rc::new(Dielectric::new(1.5));
let mat2 = Rc::new(Lambert::new(Color::new(0.4, 0.2, 0.1)));
let mat3 = Rc::new(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0));
let sphere1 = Sphere::new(Point3::new(0.0, 1.0, 0.0), 1.0, mat1);
let sphere2 = Sphere::new(Point3::new(-4.0, 1.0, 0.0), 1.0, mat2);
let sphere3 = Sphere::new(Point3::new(4.0, 1.0, 0.0), 1.0, mat3);
world.push(Box::new(sphere1));
world.push(Box::new(sphere2));
world.push(Box::new(sphere3));
world
}
相機和影像
const RATIO: f64 = 3.0 / 2.0;
const WIDTH: u64 = 1200;
const HEIGHT: u64 = ((WIDTH as f64) / RATIO) as u64;
const SAMPLES_PER_PIXEL: u64 = 500;
const MAX_DEPTH: u64 = 50;
let world = random_scene();
let camera = Camera::new(
Point3::new(13.0, 2.0, 3.0),
Point3::new(0.0, 0.0, 0.0),
Vector3::new(0.0, 1.0, 0.0),
20.0,
RATIO,
0.1,
10.0,
);
效果
總結
生成了最終的影像。在做的過程中,很多的公式和原理弄不清楚。
只能跟著流程往下走,其餘的沒有弄懂,圖形學還是太難了。
附錄
原始碼
https://github.com/jiangbo/game/tree/main/rust/ray-tracing