0206-生成最終影像

波尔發表於2024-07-22

環境

  • 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

相關文章