Skip to content
6 changes: 5 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build, Tests and Examples
name: Build, Tests, Lint and Examples

on: [push]

Expand All @@ -9,6 +9,10 @@ jobs:

steps:
- uses: actions/checkout@v1
- name: Install Clippy
run: rustup component add clippy
- name: Run Clippy
run: cargo clippy -- -D errors
- name: Build
run: cargo build --verbose
- name: Run tests
Expand Down
Binary file modified demo/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 9 additions & 9 deletions src/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ impl SimpleCamera {
//let viewPlaneHalfHeight = aspectRatio*viewPlaneHalfWidth

SimpleCamera {
location: location,
location,

camz: camz,
camz,
camx: camx * aspect_ratio,
camy: camy,
camy,

tax: angle.tan(),
tay: angle.tan()
Expand Down Expand Up @@ -197,17 +197,17 @@ impl FlatLensCamera {
//let viewPlaneHalfHeight = aspectRatio*viewPlaneHalfWidth

FlatLensCamera {
location: location,
location,

camz: camz,
camz,
camx: camx * aspect_ratio,
camy: camy,
camy,

tax: angle.tan(),
tay: angle.tan(),

aperture: aperture,
focus: focus,
aperture,
focus,
}
}
}
Expand All @@ -224,7 +224,7 @@ impl Camera for FlatLensCamera {
let ro = self.location + Vector3::new(point_lens[0], point_lens[1], 0.0);

Ray {
ro: ro,
ro,
rd: (focal_point - ro).normalize()
}

Expand Down
32 changes: 16 additions & 16 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Color {

impl Color {
pub fn new(r:f64, g:f64, b:f64) -> Color {
return Color {
Color {
rgb: Vector3::new(r,g,b)
}
}
Expand All @@ -20,40 +20,40 @@ impl Color {
}

pub fn white() -> Color {
return Color::new(1f64,1f64,1f64);
Color::new(1f64,1f64,1f64)
}
pub fn red() -> Color {
return Color::new(1f64,0f64,0f64);
Color::new(1f64,0f64,0f64)
}
pub fn blue() -> Color {
return Color::new(0f64,0f64,01f64);
Color::new(0f64,0f64,01f64)
}
pub fn green() -> Color {
return Color::new(0f64,1f64,0f64);
Color::new(0f64,1f64,0f64)
}

pub fn to_u8(&self) -> (u8, u8, u8) {
return ((self.rgb[0] * 255f64).min(255f64) as u8, (self.rgb[1] * 255f64).min(255f64) as u8, (self.rgb[2] * 255f64).min(255f64) as u8);
pub fn as_u8(&self) -> (u8, u8, u8) {
((self.rgb[0] * 255f64).min(255f64) as u8, (self.rgb[1] * 255f64).min(255f64) as u8, (self.rgb[2] * 255f64).min(255f64) as u8)
}

pub fn to_vec(&self) -> Vector3<f64> {
return self.rgb.clone();
pub fn as_vec(&self) -> Vector3<f64> {
self.rgb
}

pub fn clamp(&self, val: f64) -> Color {
return Color::new(self.rgb.x.min(val), self.rgb.y.min(val), self.rgb.z.min(val));
Color::new(self.rgb.x.min(val), self.rgb.y.min(val), self.rgb.z.min(val))
}

pub fn min() -> Color {
return Color::new(1./255.,1./255.,1./255.);
Color::new(1./255.,1./255.,1./255.)
}

pub fn ignore_nan(&self) -> Color {
return Color::new(
Color::new(
if self.rgb.x.is_nan() { 0. } else { self.rgb.x },
if self.rgb.y.is_nan() { 0. } else { self.rgb.y },
if self.rgb.z.is_nan() { 0. } else { self.rgb.z },
);
)
}

/// Blend this color with another color using the given factor
Expand All @@ -65,7 +65,7 @@ impl Color {
/// # Returns
/// A new color that is a blend of this color and the other color
pub fn blend(&self, other: &Color, factor: f64) -> Color {
let clamped_factor = factor.max(0.0).min(1.0);
let clamped_factor = factor.clamp(0.0, 1.0);
let self_factor = 1.0 - clamped_factor;

Color::new(
Expand Down Expand Up @@ -97,7 +97,7 @@ impl Mul<Color> for Color {
type Output = Color;

fn mul(self, _rhs: Color) -> Color {
Color {rgb: (_rhs * self.to_vec()).to_vec() }
Color {rgb: (_rhs * self.as_vec()).as_vec() }
}
}

Expand All @@ -122,7 +122,7 @@ impl Add<Vector3<f64>> for Color {

fn add(self, _rhs: Vector3<f64>) -> Color {
Color {
rgb: _rhs + &self.rgb
rgb: _rhs + self.rgb
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use crate::geometry::_rand::Rng;
use std::f64;

pub fn rand() -> f64 {
return _rand::thread_rng().gen_range(0.,1.);
_rand::thread_rng().gen_range(0.,1.)
}

pub fn random_point_on_unit_sphere() -> Vector3<f64>{
let u = rand();
let v = rand();
return point_on_unit_sphere(u, v);
point_on_unit_sphere(u, v)
}

pub fn point_on_unit_sphere(u: f64, v: f64) -> Vector3<f64>{
Expand All @@ -24,21 +24,21 @@ pub fn point_on_unit_sphere(u: f64, v: f64) -> Vector3<f64>{
let x = r * sin_phi * cos_theta;
let y = r * sin_phi * sin_theta;
let z = r * cos_phi;
return Vector3::new(x, y, z);
Vector3::new(x, y, z)
}

pub fn random_point_on_disc(radius: f64) -> Vector2<f64>{
let r = radius * rand().sqrt();
let theta = rand() * 2.0 * f64::consts::PI;
return Vector2::new(r * theta.cos(), r * theta.sin());
Vector2::new(r * theta.cos(), r * theta.sin())
}

pub fn uniform_sample_hemisphere(r1: f64, r2: f64) -> Vector3<f64>{
let sin_theta = (1. - r1 * r1).sqrt();
let phi = 2. * f64::consts::PI * r2;
let x = sin_theta * phi.cos();
let z = sin_theta * phi.sin();
return Vector3::new(x, r1, z);
Vector3::new(x, r1, z)
}

// Transform into the world of vec
Expand Down
2 changes: 1 addition & 1 deletion src/intersection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct MediumIntersection {

impl cmp::PartialEq for Intersection {
fn eq(&self, other: &Intersection) -> bool {
&self.point == &other.point
self.point == other.point
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/material/ambient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Ambient {

impl MaterialModel for Ambient {
fn scatter(&self, _r: &Ray, _intersection: &Intersection, _s: &Scene) -> ScatteredRay{
return ScatteredRay{ attenuate:self.albedo, ray: None };
ScatteredRay{ attenuate:self.albedo, ray: None }
}


Expand Down
2 changes: 1 addition & 1 deletion src/material/dielectric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ pub struct Dielectric {

impl MaterialModel for Dielectric {
fn scatter(&self, r: &Ray, intersection: &Intersection, _s: &Scene) -> ScatteredRay{
return scatter_dielectric(self.refractive_index, self.attenuate, r, intersection);
scatter_dielectric(self.refractive_index, self.attenuate, r, intersection)
}
}
4 changes: 2 additions & 2 deletions src/material/diffuse_light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ pub struct DiffuseLight {

impl MaterialModel for DiffuseLight {
fn scatter(&self, _r: &Ray, _intersection: &Intersection, _s: &Scene) -> ScatteredRay{
return ScatteredRay{
ScatteredRay{
attenuate:self.color * self.intensity,
ray: None };
ray: None }
}
}
41 changes: 24 additions & 17 deletions src/material/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn scatter_lambertian(albedo: Color, intersection: &Intersection) -> Scatter
ro: intersection.point,
rd: intersection.normal + random_point_on_unit_sphere(),
};
return ScatteredRay{ attenuate:albedo, ray: Some(refl) };
ScatteredRay{ attenuate:albedo, ray: Some(refl) }
}

pub fn scatter_dielectric(
Expand All @@ -46,21 +46,27 @@ pub fn scatter_dielectric(
intersection: &Intersection
) -> ScatteredRay {

let mut ni_over_nt = refractive_index; // Assumes it comes from air - TODO
let cosine;
let drn = r.rd.dot(&intersection.normal);
let outward_normal;
if drn > 0.0 {

let outward_normal = if drn > 0.0 {
// when ray shoot through object back into vacuum,
// ni_over_nt = ref_idx, surface normal has to be inverted.
cosine = drn / r.rd.norm();
outward_normal = -intersection.normal
-intersection.normal
} else {
// when ray shoots into object,
// ni_over_nt = 1 / ref_idx.
cosine = - drn / r.rd.norm();
ni_over_nt = 1.0 / refractive_index;
outward_normal = intersection.normal
intersection.normal
};

let cosine = if drn > 0.0 {
drn / r.rd.norm()
} else {
-drn / r.rd.norm()
};

let ni_over_nt = if drn > 0.0 {
refractive_index // Assumes it comes from air - TODO
} else {
1.0 / refractive_index
};

match refract(r.rd, outward_normal, ni_over_nt) {
Expand All @@ -85,26 +91,27 @@ pub fn scatter_dielectric(
}

let reflected = reflect(r.rd, intersection.normal);
return ScatteredRay {
ScatteredRay {
attenuate: Color::white(),
ray: Some(Ray {
ro: intersection.point,
rd: reflected
})
};
}
}


pub fn diffuse (pigment: Color, i: &Intersection, light_vec: &Vector3<f64>, light: &Light) -> Color {
let diffuse_scale = light_vec.normalize().dot(&i.normal) * light.intensity;
if diffuse_scale.is_sign_positive() {
return light.color * pigment * diffuse_scale;
light.color * pigment * diffuse_scale
} else {
Color::black()
}
return Color::black()
}

pub fn phong (phong: f64, r: &Ray, intersection: &Intersection, light_vec: &Vector3<f64>) -> Color {
if phong < std::f64::MIN_POSITIVE {
if phong < f64::MIN_POSITIVE {
return Color::black();
}
let ln = light_vec.normalize();
Expand All @@ -116,5 +123,5 @@ pub fn phong (phong: f64, r: &Ray, intersection: &Intersection, light_vec: &Vect
return Color::white() * spec_scale;
}

return Color::black();
Color::black()
}
2 changes: 1 addition & 1 deletion src/material/lambertian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct Lambertian {
}
impl MaterialModel for Lambertian {
fn scatter(&self, _r: &Ray, intersection: &Intersection, _s: &Scene) -> ScatteredRay{
return scatter_lambertian(self.albedo, intersection);
scatter_lambertian(self.albedo, intersection)
}
}

6 changes: 3 additions & 3 deletions src/material/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl MaterialModel for Whitted {

match shadow_intersection {
Some(_) => (),// Point in shadow...
None => out = diffuse(self.pigment, &intersection, &light_vec, &light) + phong(self.phong, &r, &intersection, &light_vec),
None => out = diffuse(self.pigment, intersection, &light_vec, light) + phong(self.phong, r, intersection, &light_vec),
}
}

Expand All @@ -34,7 +34,7 @@ impl MaterialModel for Whitted {
};
return ScatteredRay{ attenuate: out * self.reflection, ray: Some(refl) };
}
return ScatteredRay{ attenuate: out, ray: None };
ScatteredRay{ attenuate: out, ray: None }
}
}

Expand All @@ -44,6 +44,6 @@ pub struct FlatColor {

impl MaterialModel for FlatColor {
fn scatter(&self, _r: &Ray, _intersection: &Intersection, _s: &Scene) -> ScatteredRay{
return ScatteredRay{ attenuate: self.pigment, ray: None };
ScatteredRay{ attenuate: self.pigment, ray: None }
}
}
2 changes: 0 additions & 2 deletions src/material/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use crate::ray::Ray;
use crate::intersection::Intersection;
use crate::scene::Scene;

///
/// See https://google.github.io/filament//Materials.md.html#materialmodels/litmodel

///
/// In Google Filament they refer to
/// - The Lit model (standard material model)
Expand Down
6 changes: 3 additions & 3 deletions src/material/noise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ mod tests {
for z in 0..5 {
let pos = Vector3::new(x as f64, y as f64, z as f64);
let value = noise_texture.noise_value(pos);
assert!(value >= 0.0 && value <= 1.0, "Noise value out of range: {}", value);
assert!((0.0..=1.0).contains(&value), "Noise value out of range: {}", value);
}
}
}
Expand All @@ -272,7 +272,7 @@ mod tests {
for z in 0..5 {
let pos = Vector3::new(x as f64, y as f64, z as f64);
let value = noise_texture.noise_value(pos);
assert!(value >= 0.0 && value <= 1.0, "FBM value out of range: {}", value);
assert!((0.0..=1.0).contains(&value), "FBM value out of range: {}", value);
}
}
}
Expand All @@ -294,7 +294,7 @@ mod tests {
for z in 0..5 {
let pos = Vector3::new(x as f64, y as f64, z as f64);
let value = noise_texture.noise_value(pos);
assert!(value >= 0.0 && value <= 1.0, "Marble value out of range: {}", value);
assert!((0.0..=1.0).contains(&value), "Marble value out of range: {}", value);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/material/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl MaterialModel for NormalShade {
fn scatter(&self, _r: &Ray, intersection: &Intersection, _s: &Scene) -> ScatteredRay{
let angle = intersection.normal.dot(&Vector3::new(0., 1., 0.));
let c = Color::white() * intersection.normal.abs() * angle * angle * angle;
return ScatteredRay{ attenuate: c, ray: None };
ScatteredRay{ attenuate: c, ray: None }
}
}

Expand Down
Loading