Skip to content

Commit

Permalink
Merge pull request #10 from soumyasen1809/tasks
Browse files Browse the repository at this point in the history
Final image render
  • Loading branch information
soumyasen1809 authored Aug 15, 2024
2 parents 039f435 + b70e813 commit b3745e7
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ authors = ["Sen"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lib ={ path = "lib"} # needed for the tests to work
rand="0.3.14"

[[bin]]
name = "bin"
Expand Down
45 changes: 36 additions & 9 deletions lib/src/utilities/camera.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
use rand::Rng;

use super::{
color::Color, geometry::Hittable, interval::Interval, material::Scatter, point::Point3,
ray::Ray, vector3::Vector3,
color::Color,
geometry::Hittable,
interval::Interval,
material::Scatter,
point::Point3,
ray::Ray,
vector3::{Cross, Vector3},
};
use std::{fs::File, io::Write};

#[derive(Default, Clone)]
pub struct CameraFrameBasis {
u: Vector3,
v: Vector3,
w: Vector3,
}

#[derive(Default, Clone)]
pub struct Camera {
pub aspect_ratio: f64,
pub image_width: i32,
pub samples_per_pixel: i32,
pub max_depth: i32, // Maximum number of ray bounces
pub vertical_field_of_view: f64,
pub look_from: Point3,
pub look_at: Point3,
pub vertical_camera_up: Vector3,
image_height: i32,
camera_center: Point3,
pixel00_loc: Point3, // Location of pixel 0, 0
pixel_delta_u: Vector3, // Offset to pixel to the right
pixel_delta_v: Vector3, // Offset to pixel below
pixel_samples_scale: f64, // Color scale factor for a sum of pixel samples
frame_basis: CameraFrameBasis,
}

impl Camera {
Expand All @@ -26,6 +43,10 @@ impl Camera {
aspect_ratio: 1.0,
image_width: 100,
samples_per_pixel: 10,
vertical_field_of_view: 90.0,
look_from: Point3::new(0.0, 0.0, 0.0),
look_at: Point3::new(0.0, 0.1, -1.0),
vertical_camera_up: Vector3::new(0.0, 1.0, 0.0),
..Default::default() // this is possible using the derive(Default)
}
}
Expand Down Expand Up @@ -65,25 +86,31 @@ impl Camera {
}

self.pixel_samples_scale = 1.0 / self.samples_per_pixel as f64;
self.camera_center = Point3::new(0.0, 0.0, 0.0);
self.camera_center = self.look_from;

// Camera
let viewport_height: f64 = 2.0;
// Camera - Viewport dimensions
let focal_length: f64 = (self.look_from - self.look_at).as_vec().length();
let theta: f64 = self.vertical_field_of_view.to_radians();
let viewport_height: f64 = 2.0 * focal_length * (theta / 2.0).tan();
let viewport_width: f64 =
viewport_height * (self.image_width as f64 / self.image_height as f64);

// Calculate the basis vectors for the camera frame
self.frame_basis.w = (self.look_from - self.look_at).as_vec().unit_vector();
self.frame_basis.u = (self.vertical_camera_up.cross_prod(self.frame_basis.w)).unit_vector();
self.frame_basis.v = self.frame_basis.w.cross_prod(self.frame_basis.u);

// Calculate the vectors across the horizontal and down the vertical viewport edges
let viewport_u: Vector3 = Vector3::new(viewport_width, 0.0, 0.0);
let viewport_v: Vector3 = Vector3::new(0.0, -viewport_height, 0.0);
let viewport_u: Vector3 = self.frame_basis.u * viewport_width; // Vector across viewport horizontal edge
let viewport_v: Vector3 = -self.frame_basis.v * viewport_height; // Vector down viewport vertical edge

// Calculate the horizontal and vertical delta vectors from pixel to pixel
self.pixel_delta_u = viewport_u / (self.image_width as f64);
self.pixel_delta_v = viewport_v / (self.image_height as f64);

// Calculate the location of the upper left pixel
let focal_length: f64 = 1.0;
let viewport_origin: Point3 = self.camera_center
- Vector3::new(0.0, 0.0, focal_length)
- (self.frame_basis.w * focal_length)
- (viewport_u / 2.0)
- (viewport_v / 2.0);

Expand Down
98 changes: 76 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,100 @@
use rand::Rng;

use lib::utilities::{
camera::Camera,
color::Color,
geometry::{Hittable, Sphere},
material::{Dielectric, Lambertian, Metal},
point::Point3,
vector3::Vector3,
};

const NUMBER_BALLS: i32 = 5;

const ASPECT_RATIO: f64 = 16.0 / 9.0;
const IMAGE_WIDTH: i32 = 384;
const SAMPLES_PER_PIXEL: i32 = 100;
const IMAGE_WIDTH: i32 = 640;
const SAMPLES_PER_PIXEL: i32 = 500;
const MAX_DEPTH: i32 = 50;
const VERTICAL_FOV: f64 = 40.0;

fn main() {
// https://raytracing.github.io/books/RayTracingInOneWeekend.html

// World
let mut world: Vec<Box<dyn Hittable>> = Vec::new();

let material_ground = Box::new(Lambertian::new(Color::new(0.8, 0.8, 0.0)));
let material_center = Box::new(Lambertian::new(Color::new(0.1, 0.2, 0.5)));
let material_left = Box::new(Dielectric::new(1.33));
let material_right = Box::new(Metal::new(Color::new(0.8, 0.6, 0.2), 1.0));
let material_bubble = Box::new(Dielectric::new(1.0 / 1.33));

// Scene - ground
let material_ground = Box::new(Lambertian::new(Color::new(0.8, 0.8, 0.8)));
world.push(Box::new(Sphere::new(
Point3::new(0.0, -100.5, -1.0),
100.0,
Point3::new(0.0, -1000.0, 0.0),
1000.0,
material_ground,
)));

// Scene - small balls (random)
for x_index in -NUMBER_BALLS..NUMBER_BALLS {
for y_index in -NUMBER_BALLS..NUMBER_BALLS {
let choose_material_random: f64 = rand::thread_rng().r#gen::<f64>();
let center = Point3::new(
(x_index as f64) + (0.9 * rand::thread_rng().r#gen::<f64>()),
0.2,
(y_index as f64) + (0.9 * rand::thread_rng().r#gen::<f64>()),
);
if choose_material_random < 0.6 {
// Lambertian
let material_lambertian = Box::new(Lambertian::new(Color::new(
rand::thread_rng().r#gen::<f64>(),
rand::thread_rng().r#gen::<f64>(),
rand::thread_rng().r#gen::<f64>(),
)));
world.push(Box::new(Sphere::new(center, 0.2, material_lambertian)));
} else if choose_material_random < 0.85 {
// Metal
let material_metal = Box::new(Metal::new(
Color::new(
rand::thread_rng().r#gen::<f64>(),
rand::thread_rng().r#gen::<f64>(),
rand::thread_rng().r#gen::<f64>(),
),
rand::thread_rng().r#gen::<f64>(),
));
world.push(Box::new(Sphere::new(center, 0.2, material_metal)));
} else {
// Glass
let material_glass = Box::new(Dielectric::new(1.33));
world.push(Box::new(Sphere::new(center, 0.2, material_glass)));
}
}
}

// Scene - big balls with Glass material
let material_glass = Box::new(Dielectric::new(1.0 / 1.55));
world.push(Box::new(Sphere::new(
Point3::new(0.0, 0.0, -1.2),
0.5,
material_center,
Point3::new(-8.0, 1.0, 0.0),
1.0,
material_glass,
)));
let material_bubble = Box::new(Dielectric::new(1.55));
world.push(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.5,
material_left,
Point3::new(0.0, 1.0, 0.0),
1.0,
material_bubble,
)));

// Scene - big ball with Lambertian material
let material_lambertian = Box::new(Lambertian::new(Color::new(0.4, 0.2, 0.1)));
world.push(Box::new(Sphere::new(
Point3::new(1.0, 0.0, -1.0),
0.5,
material_right,
Point3::new(-4.0, 1.0, 0.0),
1.0,
material_lambertian,
)));

// Scene - big ball with Metal material
let material_metal = Box::new(Metal::new(Color::new(0.7, 0.6, 0.5), 0.2));
world.push(Box::new(Sphere::new(
Point3::new(-1.0, 0.0, -1.0),
0.4,
material_bubble,
Point3::new(4.0, 1.0, 0.0),
1.0,
material_metal,
)));

// Camera
Expand All @@ -55,5 +103,11 @@ fn main() {
cam.image_width = IMAGE_WIDTH;
cam.samples_per_pixel = SAMPLES_PER_PIXEL;
cam.max_depth = MAX_DEPTH;

cam.vertical_field_of_view = VERTICAL_FOV; // Zooms in/out of the image
cam.look_from = Point3::new(13.0, 2.0, 3.0);
cam.look_at = Point3::new(0.0, 0.0, 0.0);
cam.vertical_camera_up = Vector3::new(0.0, 1.0, 0.0);

cam.render(world);
}

0 comments on commit b3745e7

Please sign in to comment.