From 0c5c6381fceaac3cfb89f0df1df0ad5be406623b Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sat, 8 Sep 2018 17:17:29 -0700 Subject: [PATCH] Start of surface normal support. --- bheisler/src/lib.rs | 17 +++++++++++++++++ bheisler/src/point.rs | 15 +++++++++++++++ bheisler/src/rendering.rs | 22 +++++++++++++++++++++ bheisler/src/scene.rs | 8 ++++++++ bheisler/src/vector.rs | 40 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+) diff --git a/bheisler/src/lib.rs b/bheisler/src/lib.rs index 7132b49..807c24d 100644 --- a/bheisler/src/lib.rs +++ b/bheisler/src/lib.rs @@ -17,6 +17,9 @@ pub fn render(scene: &Scene) -> image::DynamicImage { let ray = rendering::Ray::create_prime(x, y, scene); if let Some(intersection) = scene.trace(&ray) { + let hit_point = ray.origin + (&ray.direction * intersection.distance); + let surface_normal = intersection.object.surface_normal(&hit_point); + let direction_to_light = -scene.light.direction; let c = &intersection.object.color(); image.put_pixel(x, y, image::Rgba(c.to_rgba())) } else { @@ -34,6 +37,7 @@ fn test_can_render_scene() { use rendering::Plane; use rendering::Sphere; use scene::Color; + use scene::Light; use vector::Vector3; let scene = Scene { @@ -128,6 +132,19 @@ fn test_can_render_scene() { }, }), ], + light: Light { + direction: Vector3 { + x: 0.0, + y: 0.0, + z: -1.0, + }, + color: Color { + red: 1.0, + green: 1.0, + blue: 1.0, + }, + intensity: 0.0, + }, }; let img: image::DynamicImage = render(&scene); diff --git a/bheisler/src/point.rs b/bheisler/src/point.rs index 78a04f7..309a07f 100644 --- a/bheisler/src/point.rs +++ b/bheisler/src/point.rs @@ -1,5 +1,8 @@ +use std::ops::Add; use std::ops::Sub; +use vector::Vector3; + #[derive(Clone, Copy)] pub struct Point { pub x: f32, @@ -17,6 +20,18 @@ impl Point { } } +impl Add for Point { + type Output = Point; + + fn add(self, other: Vector3) -> Point { + Point { + x: self.x + other.x, + y: self.y + other.y, + z: self.z + other.z, + } + } +} + impl Sub for Point { type Output = Point; diff --git a/bheisler/src/rendering.rs b/bheisler/src/rendering.rs index 8c075e9..ffc6ac3 100644 --- a/bheisler/src/rendering.rs +++ b/bheisler/src/rendering.rs @@ -5,6 +5,7 @@ use vector::Vector3; pub trait Intersectable { fn intersect(&self, ray: &Ray) -> Option; + fn surface_normal(&self, hit_point: &Point) -> Vector3; } pub struct Sphere { @@ -37,6 +38,10 @@ impl Intersectable for Sphere { let distance = if t0 < t1 { t0 } else { t1 }; Some(distance) } + + fn surface_normal(&self, hit_point: &Point) -> Vector3 { + Vector3::from(*hit_point - self.center).normalize() + } } pub struct Plane { @@ -58,6 +63,10 @@ impl Intersectable for Plane { } None } + + fn surface_normal(&self, _: &Point) -> Vector3 { + -self.normal + } } pub enum Element { @@ -72,6 +81,12 @@ impl Element { Element::Plane(ref p) => &p.color, } } + pub fn surface_normal(&self, hit_point: &Point) -> Vector3 { + match *self { + Element::Sphere(ref s) => s.surface_normal(hit_point), + Element::Plane(ref p) => p.surface_normal(hit_point), + } + } } impl Intersectable for Element { @@ -81,6 +96,13 @@ impl Intersectable for Element { Element::Plane(ref p) => p.intersect(ray), } } + + fn surface_normal(&self, hit_point: &Point) -> Vector3 { + match *self { + Element::Sphere(ref s) => s.surface_normal(hit_point), + Element::Plane(ref p) => p.surface_normal(hit_point), + } + } } pub struct Ray { diff --git a/bheisler/src/scene.rs b/bheisler/src/scene.rs index 3d3ce06..4dca3f7 100644 --- a/bheisler/src/scene.rs +++ b/bheisler/src/scene.rs @@ -1,6 +1,7 @@ use rendering::Element; use rendering::Intersectable; use rendering::Ray; +use vector::Vector3; pub struct Intersection<'a> { pub distance: f32, @@ -31,11 +32,18 @@ impl Color { } } +pub struct Light { + pub direction: Vector3, + pub color: Color, + pub intensity: f32, +} + pub struct Scene { pub width: u32, pub height: u32, pub fov: f32, pub elements: Vec, + pub light: Light, } impl Scene { diff --git a/bheisler/src/vector.rs b/bheisler/src/vector.rs index b029765..0d110d8 100644 --- a/bheisler/src/vector.rs +++ b/bheisler/src/vector.rs @@ -1,6 +1,10 @@ use point::Point; +use std::ops::Add; use std::ops::Div; +use std::ops::Mul; +use std::ops::Neg; +#[derive(Clone, Copy)] pub struct Vector3 { pub x: f32, pub y: f32, @@ -37,6 +41,42 @@ impl<'a> Div for &'a Vector3 { } } +impl<'a> Mul for &'a Vector3 { + type Output = Vector3; + + fn mul(self, rhs: f32) -> Vector3 { + Vector3 { + x: self.x * rhs, + y: self.y * rhs, + z: self.z * rhs, + } + } +} + +impl Add for Vector3 { + type Output = Vector3; + + fn add(self, rhs: Vector3) -> Vector3 { + Vector3 { + x: rhs.x + self.x, + y: rhs.y + self.y, + z: rhs.z + self.z, + } + } +} + +impl Neg for Vector3 { + type Output = Vector3; + + fn neg(self) -> Vector3 { + Vector3 { + x: -self.x, + y: -self.y, + z: -self.z, + } + } +} + impl From for Vector3 { fn from(p: Point) -> Self { Vector3 {