Skip to content

Commit

Permalink
added rng antialiasing to the system
Browse files Browse the repository at this point in the history
  • Loading branch information
waridh committed Aug 17, 2024
1 parent 11066fc commit 887d335
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 16 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ edition = "2021"
[dependencies]
anyhow = "1.0.86"
indicatif = "0.17.8"
rand = "0.8.5"
51 changes: 42 additions & 9 deletions src/camera.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
use crate::{color, hittable::Hittable, ray, vec3};
use indicatif::ProgressIterator;
use rand::{self, rngs::ThreadRng, Rng};
use std::{f32::INFINITY, ops::Range, rc::Rc};

const ZERO_TO_INFINITY: Range<f32> = 0f32..INFINITY;
pub struct Camera {
pub aspect_ratio: f32,
pub image_width: usize,
pub samples_per_pixel: usize,
image_height: usize,
pixel00: vec3::Vec3,
pixel_delta_u: vec3::Vec3,
pixel_delta_v: vec3::Vec3,
center: Rc<vec3::Vec3>,
pixel_sample_scale: f32,
rng: ThreadRng,
}

impl Camera {
pub fn new(aspect_ratio: f32, image_width: usize, focal_length: f32) -> Self {
pub fn new(
aspect_ratio: f32,
image_width: usize,
focal_length: f32,
samples_per_pixel: usize,
) -> Self {
let rng = rand::thread_rng();
let image_height = match ((image_width as f32) / aspect_ratio) as usize {
x if x < 1 => 1,
x => x,
Expand All @@ -39,36 +49,59 @@ impl Camera {
- (viewport_v / 2.);
let pixel00 = viewport_upper_left + (pixel_delta_u + pixel_delta_v) * 0.5;

let pixel_sample_scale = 1. / (samples_per_pixel as f32);

Camera {
aspect_ratio,
image_width,
samples_per_pixel,
image_height,
pixel00,
pixel_delta_u,
pixel_delta_v,
center,
pixel_sample_scale,
rng,
}
}
/// Reders the scene with side-effects going straight to stdout

/// Renders the scene with side-effects going straight to stdout
/// A buffer writer would improve the performance of this function
pub fn render(&self, world: &impl Hittable) {
pub fn render(&mut self, world: &impl Hittable) {
// render

println!("P3\n{} {}\n255", self.image_width, self.image_height);

for j in (0..self.image_height).progress() {
for i in 0..self.image_width {
let pixel_center =
self.pixel00 + (self.pixel_delta_u * i) + (self.pixel_delta_v * j);
let raydir = pixel_center - self.center.as_ref();
let r = ray::Ray::new(raydir, &self.center);
let pixel = Camera::ray_color(r, world);
let mut pixel = color::Color::from_args(0., 0., 0.);
for _ in 0..self.samples_per_pixel {
let r = self.get_ray(i, j);
pixel += Camera::ray_color(r, world);
}

println!("{}", pixel);
println!("{}", pixel * self.pixel_sample_scale);
}
}
}

fn get_ray(&mut self, i: usize, j: usize) -> ray::Ray {
let offset = self.sample_square();
let pixel_center = self.pixel00
+ (self.pixel_delta_u * ((i as f32) + offset[0]))
+ (self.pixel_delta_v * ((j as f32) + offset[1]));
let raydir = pixel_center - self.center.as_ref();
ray::Ray::new(raydir, &self.center)
}

fn sample_square(&mut self) -> vec3::Vec3 {
vec3::Vec3(
self.rng.gen_range(-0.5..0.5),
self.rng.gen_range(-0.5..0.5),
0.,
)
}

fn ray_color(r: ray::Ray, world: &impl Hittable) -> color::Color {
match world.hit(&r, &ZERO_TO_INFINITY) {
Some(t) => {
Expand Down
62 changes: 59 additions & 3 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{fmt, ops};
/// The Color newtype is a vec3 that represents a color.
/// Invariant:
/// The fields of this struct must be a float between 0 and 1.
#[derive(Debug, PartialEq)]
pub struct Color(vec3::Vec3);

impl Color {
Expand All @@ -24,16 +25,27 @@ impl From<(f32, f32, f32)> for Color {
}
}

/// Used to clamp the color output
fn clamp(legal_range: &ops::Range<f32>, val: f32) -> f32 {
match val {
x if x > legal_range.end => legal_range.end,
x if x < legal_range.start => legal_range.start,
x => x,
}
}

impl fmt::Display for Color {
/// Color has a different byte representation in ppm than vec3.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let r = self.0[0];
let g = self.0[1];
let b = self.0[2];

let ir = (255.999 * r) as u8;
let ig = (255.999 * g) as u8;
let ib = (255.999 * b) as u8;
let legal_range = 0f32..0.999;

let ir = (255.999 * clamp(&legal_range, r)) as u8;
let ig = (255.999 * clamp(&legal_range, g)) as u8;
let ib = (255.999 * clamp(&legal_range, b)) as u8;

write!(f, "{} {} {}", ir, ig, ib)
}
Expand All @@ -46,6 +58,12 @@ impl ops::Index<usize> for Color {
}
}

impl ops::IndexMut<usize> for Color {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}

impl ops::Mul<f32> for Color {
type Output = Color;
fn mul(self, rhs: f32) -> Self::Output {
Expand All @@ -69,6 +87,26 @@ impl ops::Add<Color> for Color {
}
}

impl ops::AddAssign<Color> for Color {
fn add_assign(&mut self, rhs: Color) {
for i in 0..3 {
self[i] += rhs[i]
}
}
}

impl ops::DivAssign<f32> for Color {
fn div_assign(&mut self, rhs: f32) {
self.0 /= rhs
}
}

impl ops::DivAssign<usize> for Color {
fn div_assign(&mut self, rhs: usize) {
self.0 /= rhs
}
}

#[cfg(test)]
mod test {
use super::*;
Expand All @@ -89,4 +127,22 @@ mod test {
assert_eq!(0.25, input[1]);
assert_eq!(0.125, input[2]);
}

#[test]
fn color_assign_scalar_division() {
let mut left = Color::from_args(3., 6., 9.);
left /= 2.;
let expected = Color::from_args(1.5, 3., 4.5);

assert_eq!(left, expected);
}

#[test]
fn color_assign_scalar_division_usize() {
let mut left = Color::from_args(3., 6., 9.);
left /= 2;
let expected = Color::from_args(1.5, 3., 4.5);

assert_eq!(left, expected);
}
}
7 changes: 3 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use hittable::Hittable;
use indicatif::ProgressIterator;
use std::{f32::INFINITY, ops::Range, rc::Rc};
use std::rc::Rc;

mod camera;
mod color;
Expand All @@ -12,8 +10,9 @@ mod vec3;
fn main() {
let aspect_ratio: f32 = 5. / 4.;
let image_width = 1200usize;
let samples_per_pixel = 10;

let camera = camera::Camera::new(aspect_ratio, image_width, 1.0);
let mut camera = camera::Camera::new(aspect_ratio, image_width, 1.0, samples_per_pixel);
// World
let sphere_1 = Rc::new(sphere::Sphere::from((0., 0., -1., 0.5)));
let sphere_2 = Rc::new(sphere::Sphere::from((1.0, -100.5, -1., 100.)));
Expand Down
31 changes: 31 additions & 0 deletions src/vec3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ impl ops::Div<f32> for &Vec3 {
}
}

/// Tested
impl ops::DivAssign<f32> for Vec3 {
fn div_assign(&mut self, rhs: f32) {
self.0 /= rhs;
Expand All @@ -239,6 +240,16 @@ impl ops::DivAssign<f32> for Vec3 {
}
}

/// Tested
impl ops::DivAssign<usize> for Vec3 {
fn div_assign(&mut self, rhs: usize) {
let converted = rhs as f32;
self.0 /= converted;
self.1 /= converted;
self.2 /= converted;
}
}

impl ops::Index<usize> for Vec3 {
type Output = f32;
fn index(&self, index: usize) -> &Self::Output {
Expand All @@ -251,6 +262,17 @@ impl ops::Index<usize> for Vec3 {
}
}

impl ops::IndexMut<usize> for Vec3 {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.0,
1 => &mut self.1,
2 => &mut self.2,
_ => panic!("Index out of bounds"),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -430,6 +452,15 @@ mod tests {
assert_eq!(left, expected);
}

#[test]
fn vec3_assign_scalar_division_usize() {
let mut left = Vec3(3., 6., 9.);
left /= 2;
let expected = Vec3(1.5, 3., 4.5);

assert_eq!(left, expected);
}

#[test]
fn squared_length() {
let input = Vec3(3., 6., 9.);
Expand Down

0 comments on commit 887d335

Please sign in to comment.