Skip to content

Commit

Permalink
feat: added materials
Browse files Browse the repository at this point in the history
  • Loading branch information
Wafelack committed Nov 24, 2020
1 parent 6d071b8 commit 9830886
Show file tree
Hide file tree
Showing 10 changed files with 566,261 additions and 123,796 deletions.
689,930 changes: 566,149 additions & 123,781 deletions image.ppm

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ pub fn write_color(pixel_color: color, samples_per_pixel: i32) {
r = (scale * r).sqrt();
g = (scale * g).sqrt();
b = (scale * b).sqrt();

println!(
"{} {} {}",
"{} {} {}",
(256. * clamp(r, 0., 0.999)) as i32,
(256. * clamp(g, 0., 0.999)) as i32,
(256. * clamp(b, 0., 0.999)) as i32
Expand Down
21 changes: 16 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,48 @@ mod colors;
mod objects;
mod utils;
mod ray;
mod material;

use camera::Camera;
use vec3::*;
use colors::write_color;
use objects::{hittable::*, hittable_list::*, sphere::*};
use utils::*;
use ray::*;
use material::material::*;



fn main() {
// Image
const ASPECT_RATIO: f32 = 16.0 / 9.0;
const IMAGE_WIDTH: i32 = 512;
const IMAGE_WIDTH: i32 = 1024;
const IMAGE_HEIGHT: i32 = (IMAGE_WIDTH as f32 / ASPECT_RATIO) as i32;
const SAMPLES_PER_PIXEL: i32 = 9;
const SAMPLES_PER_PIXEL: i32 = 8;
const MAX_DEPTH: i32 = 50;

// World
let mut world = HittableList::new();
world.add(Rc::new(Sphere::new(point3::from(0., 0., -1.), 0.5)));
world.add(Rc::new(Sphere::new(point3::from(0., -100.5, -1.), 100.)));

let material_ground = Rc::new(Lambertian::from(color::from(0.8,0.8,0.0)));
let material_center = Rc::new(Lambertian::from(color::from(0.7,0.3,0.3)));
let material_left = Rc::new(Metal::from(color::from(0.8,0.8,0.8)));
let material_right = Rc::new(Metal::from(color::from(0.8,0.6,0.2)));

world.add(Rc::new(Sphere::new(point3::from(0.,-100.5,-1.), 100., material_ground)));
world.add(Rc::new(Sphere::new(point3::from(0.,0.0,-1.), 0.5, material_center)));
world.add(Rc::new(Sphere::new(point3::from(-1.,0.0,-1.), 0.5, material_left)));
world.add(Rc::new(Sphere::new(point3::from(1.,0.0,-1.), 0.5, material_right)));


// Camera
let cam = Camera::new();

// Render
println!("P3\n{} {}\n255", IMAGE_WIDTH, IMAGE_HEIGHT);

for j in (0..IMAGE_HEIGHT).rev() {
eprint!("\rScanlines remaining: {} ", j);
eprint!("\rScanlines remaining: {}/{}", j, IMAGE_HEIGHT);
io::stdout().flush().unwrap();
for i in 0..IMAGE_WIDTH {
let mut pixel_color = color::new();
Expand Down
45 changes: 45 additions & 0 deletions src/material/material.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::{ray::*, vec3::*, objects::hittable::HitRecord};

pub trait Material {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut color, scattered: &mut Ray) -> bool;
}
#[derive(Copy, Clone)]
pub struct Lambertian {
pub albedo: color,
}
impl Lambertian {
pub fn from(a: color) -> Self {
Self {albedo: a}
}
}
impl Material for Lambertian {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut color, scattered: &mut Ray) -> bool {
let mut scatter_direction = rec.normal + color::random_unit_vector();

if scatter_direction.near_zero() {
scatter_direction = rec.normal;
}

*scattered = Ray::new(rec.p, scatter_direction);
*attenuation = self.albedo;
true

}
}
#[derive(Copy, Clone)]
pub struct Metal {
pub albedo: color,
}
impl Metal {
pub fn from(a: color) -> Self {
Self {albedo: a}
}
}
impl Material for Metal {
fn scatter(&self, r_in: Ray, rec: HitRecord, attenuation: &mut color, scattered: &mut Ray) -> bool {
let reflected = reflect(unit_vector(r_in.direction()), rec.normal);
*scattered = Ray::new(rec.p, reflected);
*attenuation = self.albedo;
dot(scattered.direction(), rec.normal) > 0.
}
}
1 change: 1 addition & 0 deletions src/material/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod material;
8 changes: 6 additions & 2 deletions src/objects/hittable.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::{ray::*, vec3::*};
use crate::{vec3::*, ray::*,material::material::*};
use std::rc::Rc;

#[derive(Copy, Clone)]

#[derive(Clone)]
pub struct HitRecord {
pub p: point3,
pub normal: Vec3,
pub mat_ptr: Rc<dyn Material>,
pub t: f32,
pub front_face: bool,
}
Expand All @@ -12,6 +15,7 @@ impl HitRecord {
Self {
p: Vec3::new(),
normal: Vec3::new(),
mat_ptr: Rc::new(Lambertian::from(color::new())),
t: 0.,
front_face: true,
}
Expand Down
4 changes: 2 additions & 2 deletions src/objects/hittable_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ impl Hittable for HittableList {
for object in &self.objects {
if object.hit(r, t_min, closest_so_far, &mut temp_rec) {
hit_anything = true;
closest_so_far = (&temp_rec).t;
*rec = temp_rec;
closest_so_far = temp_rec.clone().t;
*rec = temp_rec.clone();
}
}
hit_anything
Expand Down
8 changes: 6 additions & 2 deletions src/objects/sphere.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use crate::{objects::hittable::*, ray::*, vec3::*};
use crate::{objects::hittable::*, ray::*, vec3::*, material::material::Material};
use std::rc::Rc;

pub struct Sphere {
pub center: point3,
pub radius: f32,
pub mat_ptr: Rc<dyn Material>
}
impl Sphere {
pub fn new(cen: point3, r: f32) -> Self {
pub fn new(cen: point3, r: f32, m: Rc<dyn Material>) -> Self {
Self {
center: cen,
radius: r,
mat_ptr: m
}
}
}
Expand Down Expand Up @@ -42,6 +45,7 @@ impl Hittable for Sphere {
rec.p = r.at(rec.t);
let outward_normal = (rec.p - self.center) / self.radius;
rec.set_face_normal(r, outward_normal);
rec.mat_ptr = self.mat_ptr.clone();

true
}
Expand Down
9 changes: 7 additions & 2 deletions src/ray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ pub fn ray_color(r: Ray, world: &impl Hittable, depth: i32) -> color {
}

if world.hit(r, 0.001, f32::INFINITY, &mut rec) {
let target = rec.p + rec.normal + color::random_in_unit_sphere();
return ray_color(Ray::new(rec.p, target - rec.p), world, depth-1) * 0.5;
let mut scattered= Ray::new(point3::new(),Vec3::new());
let mut attenuation = color::new();
if rec.mat_ptr.scatter(r, rec.clone(), &mut attenuation, &mut scattered) {
return attenuation * ray_color(scattered, world, depth - 1);
}
return color::from(0.,0.,0.);

}
let unit_direction = unit_vector(r.direction());

Expand Down
27 changes: 27 additions & 0 deletions src/vec3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ impl Vec3 {
return p;
}
}
pub fn random_unit_vector() -> Self {
unit_vector(Self::random_in_unit_sphere())
}
pub fn random_in_hemisphere(normal: Vec3) -> Self {
let in_unit_sphere = Self::random_in_unit_sphere();
if dot(in_unit_sphere, normal) > 0. {
return in_unit_sphere;
} else {
return in_unit_sphere.inv();
}
}

pub fn near_zero(&self) -> bool {
let s:f32 = 1e-8;
(self.e[0].abs() < s) && (self.e[1].abs() < s) && (self.e[2].abs() < s)
}

pub fn x(&self) -> f32 {
self.e[0]
Expand Down Expand Up @@ -80,6 +96,14 @@ impl ops::Sub for Vec3 {
}
}

impl ops::Mul for Vec3 {
type Output = Self;

fn mul(self, v: Self) -> Self {
Vec3::from(self.e[0] * v.e[0], self.e[1] * v.e[1], self.e[2] * v.e[2])
}
}

impl ops::Mul<f32> for Vec3 {
type Output = Self;

Expand Down Expand Up @@ -107,6 +131,9 @@ pub fn cross(u: Vec3, v: Vec3) -> Vec3 {
pub fn unit_vector(v: Vec3) -> Vec3 {
v / v.len()
}
pub fn reflect(v: Vec3, n: Vec3) -> Vec3 {
v - n *(2. * dot(v,n))
}

pub type point3 = Vec3;
pub type color = Vec3;

0 comments on commit 9830886

Please sign in to comment.