Start of surface normal support.

This commit is contained in:
Bill Thiede 2018-09-08 17:17:29 -07:00
parent e8d05eeaee
commit 0c5c6381fc
5 changed files with 102 additions and 0 deletions

View File

@ -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);

View File

@ -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<Vector3> 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;

View File

@ -5,6 +5,7 @@ use vector::Vector3;
pub trait Intersectable {
fn intersect(&self, ray: &Ray) -> Option<f32>;
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 {

View File

@ -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<Element>,
pub light: Light,
}
impl Scene {

View File

@ -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<f32> for &'a Vector3 {
}
}
impl<'a> Mul<f32> 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<Point> for Vector3 {
fn from(p: Point) -> Self {
Vector3 {