Added reflection material
This commit is contained in:
@@ -5,6 +5,7 @@ use nalgebra::Vector3;
|
|||||||
pub struct Material {
|
pub struct Material {
|
||||||
pub kd: Vector3<f32>,
|
pub kd: Vector3<f32>,
|
||||||
pub ks: Vector3<f32>,
|
pub ks: Vector3<f32>,
|
||||||
|
pub kr: Vector3<f32>,
|
||||||
pub shininess: f32,
|
pub shininess: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,37 +13,73 @@ impl Material {
|
|||||||
pub fn new(kd: Vector3<f64>, ks: Vector3<f64>, shininess: f64) -> Material {
|
pub fn new(kd: Vector3<f64>, ks: Vector3<f64>, shininess: f64) -> Material {
|
||||||
let kd = kd.cast();
|
let kd = kd.cast();
|
||||||
let ks = ks.cast();
|
let ks = ks.cast();
|
||||||
|
let kr = ks.cast();
|
||||||
let shininess = shininess as f32;
|
let shininess = shininess as f32;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn magenta() -> Material {
|
pub fn magenta() -> Material {
|
||||||
let kd = Vector3::new(1.0, 0.0, 1.0);
|
let kd = Vector3::new(1.0, 0.0, 1.0);
|
||||||
let ks = Vector3::new(1.0, 0.0, 1.0);
|
let ks = Vector3::new(1.0, 0.0, 1.0);
|
||||||
|
let kr = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let shininess = 0.5;
|
let shininess = 0.5;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn turquoise() -> Material {
|
pub fn turquoise() -> Material {
|
||||||
let kd = Vector3::new(0.25, 0.3, 0.7);
|
let kd = Vector3::new(0.25, 0.3, 0.7);
|
||||||
let ks = Vector3::new(0.25, 0.3, 0.7);
|
let ks = Vector3::new(0.25, 0.3, 0.7);
|
||||||
|
let kr = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let shininess = 0.5;
|
let shininess = 0.5;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn red() -> Material {
|
pub fn red() -> Material {
|
||||||
let kd = Vector3::new(0.8, 0.0, 0.3);
|
let kd = Vector3::new(0.8, 0.0, 0.3);
|
||||||
let ks = Vector3::new(0.8, 0.3, 0.0);
|
let ks = Vector3::new(0.8, 0.3, 0.0);
|
||||||
|
let kr = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let shininess = 0.5;
|
let shininess = 0.5;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn blue() -> Material {
|
pub fn blue() -> Material {
|
||||||
let kd = Vector3::new(0.0, 0.3, 0.6);
|
let kd = Vector3::new(0.0, 0.3, 0.6);
|
||||||
let ks = Vector3::new(0.3, 0.0, 0.6);
|
let ks = Vector3::new(0.3, 0.0, 0.6);
|
||||||
|
let kr = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let shininess = 0.5;
|
let shininess = 0.5;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn green() -> Material {
|
pub fn green() -> Material {
|
||||||
let kd = Vector3::new(0.0, 1.0, 0.0);
|
let kd = Vector3::new(0.0, 1.0, 0.0);
|
||||||
let ks = Vector3::new(0.0, 1.0, 0.0);
|
let ks = Vector3::new(0.0, 1.0, 0.0);
|
||||||
|
let kr = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let shininess = 0.5;
|
let shininess = 0.5;
|
||||||
Material { kd, ks, shininess }
|
Material {
|
||||||
|
kd,
|
||||||
|
ks,
|
||||||
|
kr,
|
||||||
|
shininess,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/ray.rs
65
src/ray.rs
@@ -1,5 +1,5 @@
|
|||||||
use crate::{node::Node, scene::Scene};
|
use crate::{node::Node, scene::Scene, EPSILON};
|
||||||
use nalgebra::{Matrix4, Point3, Vector3};
|
use nalgebra::{distance, Matrix4, Point3, Vector3};
|
||||||
use rand;
|
use rand;
|
||||||
|
|
||||||
const MAX_DEPTH: u8 = 5;
|
const MAX_DEPTH: u8 = 5;
|
||||||
@@ -12,13 +12,6 @@ fn random_vec() -> Vector3<f64> {
|
|||||||
fn random_unit_vec() -> Vector3<f64> {
|
fn random_unit_vec() -> Vector3<f64> {
|
||||||
random_vec().normalize()
|
random_vec().normalize()
|
||||||
}
|
}
|
||||||
fn random_on_hemisphere(normal: &Vector3<f64>) -> Vector3<f64> {
|
|
||||||
let dir = random_unit_vec();
|
|
||||||
match dir.dot(normal) > 0.0 {
|
|
||||||
true => dir,
|
|
||||||
false => -dir,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERSECTION -----------------------------------------------------------------
|
// INTERSECTION -----------------------------------------------------------------
|
||||||
pub struct Intersection {
|
pub struct Intersection {
|
||||||
@@ -105,20 +98,17 @@ impl Ray {
|
|||||||
if node.primitive.intersect_bounding_box(&ray) {
|
if node.primitive.intersect_bounding_box(&ray) {
|
||||||
// Check primitive intersection
|
// Check primitive intersection
|
||||||
if let Some(intersect) = node.primitive.intersect_ray(&ray) {
|
if let Some(intersect) = node.primitive.intersect_ray(&ray) {
|
||||||
// Check for closest distance
|
// Check for closest distance by converting to world coords
|
||||||
if intersect.distance < closest_distance {
|
let intersect = intersect.transform(&node.model, &node.inv_model);
|
||||||
closest_distance = intersect.distance;
|
let distance = distance(&ray.a, &intersect.point);
|
||||||
|
if distance < closest_distance {
|
||||||
|
closest_distance = distance;
|
||||||
closest_intersect = Some((node, intersect));
|
closest_intersect = Some((node, intersect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match closest_intersect {
|
closest_intersect
|
||||||
Some((node, intersect)) => {
|
|
||||||
Some((node, intersect.transform(&node.model, &node.inv_model)))
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// This function takes a scene and returns the color of the point where the ray intersects the scene
|
// This function takes a scene and returns the color of the point where the ray intersects the scene
|
||||||
pub fn shade_ray(&self, scene: &Scene, depth: u8) -> Option<Vector3<f32>> {
|
pub fn shade_ray(&self, scene: &Scene, depth: u8) -> Option<Vector3<f32>> {
|
||||||
@@ -143,8 +133,8 @@ impl Ray {
|
|||||||
intersect: &Intersection,
|
intersect: &Intersection,
|
||||||
depth: u8,
|
depth: u8,
|
||||||
) -> Vector3<f32> {
|
) -> Vector3<f32> {
|
||||||
let point = &intersect.point;
|
|
||||||
let normal = &intersect.normal;
|
let normal = &intersect.normal;
|
||||||
|
let point = intersect.point + EPSILON * normal;
|
||||||
let incidence = &ray.b;
|
let incidence = &ray.b;
|
||||||
|
|
||||||
let material = &node.material;
|
let material = &node.material;
|
||||||
@@ -166,42 +156,49 @@ impl Ray {
|
|||||||
let light_distance = to_light.norm() as f32;
|
let light_distance = to_light.norm() as f32;
|
||||||
let to_light = to_light.normalize();
|
let to_light = to_light.normalize();
|
||||||
|
|
||||||
let to_light_ray = Ray::new(point.clone() + 0.001 * normal, to_light);
|
//Niave Shadows
|
||||||
|
let to_light_ray = Ray::new(point, to_light);
|
||||||
if to_light_ray.light_blocked(scene, node) {
|
if to_light_ray.light_blocked(scene, node) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let n_dot_l = normal.dot(&to_light).max(0.0) as f32;
|
let n_dot_l = normal.dot(&to_light).max(0.0) as f32;
|
||||||
|
|
||||||
//Diffuse component
|
//Reflected component
|
||||||
|
let mut reflect = Vector3::zeros();
|
||||||
|
let reflect_dir = incidence - 2.0 * incidence.dot(&normal) * normal;
|
||||||
|
let reflect_ray = Ray::new(point, reflect_dir);
|
||||||
|
if let Some(col) = reflect_ray.shade_ray(scene, depth + 1) {
|
||||||
|
reflect += col.component_mul(&material.kr)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Diffuse component (Lambertian)
|
||||||
let mut diffuse = Vector3::zeros();
|
let mut diffuse = Vector3::zeros();
|
||||||
// diffuse = material.kd * n_dot_l;
|
diffuse += material.kd * n_dot_l;
|
||||||
for _ in 0..DIFFUSE_RAYS {
|
for _ in 0..DIFFUSE_RAYS {
|
||||||
let diffuse_dir = random_on_hemisphere(normal);
|
let diffuse_dir = random_unit_vec();
|
||||||
let ray = Ray::new(point.clone() + normal, diffuse_dir);
|
let diffuse_ray = Ray::new(point.clone(), diffuse_dir + normal);
|
||||||
if let Some(col) = ray.shade_ray(scene, depth + 1) {
|
if let Some(col) = diffuse_ray.shade_ray(scene, depth + 1) {
|
||||||
diffuse += col * DIFFUSE_COEFFICIENT;
|
diffuse += col * DIFFUSE_COEFFICIENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Specular component
|
//Specular component
|
||||||
let mut specular = Vector3::zeros();
|
let mut specular = Vector3::zeros();
|
||||||
if n_dot_l > 0.0 {
|
if n_dot_l < 0.0 {
|
||||||
let h = (to_light - incidence).normalize();
|
let h = (to_light - incidence).normalize();
|
||||||
let n_dot_h = normal.dot(&h).max(0.0) as f32;
|
let n_dot_h = normal.dot(&h).max(0.0) as f32;
|
||||||
specular = material.ks * n_dot_h.powf(material.shininess);
|
specular = material.ks * n_dot_h.powf(material.shininess);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Falloff
|
//Falloff
|
||||||
let falloff = 1.0
|
// let falloff = 1.0
|
||||||
/ (1.0
|
// / (1.0
|
||||||
+ light.falloff[0]
|
// + light.falloff[0]
|
||||||
+ light.falloff[1] * light_distance
|
// + light.falloff[1] * light_distance
|
||||||
+ light.falloff[2] * light_distance * light_distance);
|
// + light.falloff[2] * light_distance * light_distance);
|
||||||
|
|
||||||
let intensity = light
|
let intensity = light.colour.component_mul(&(diffuse + reflect + specular));
|
||||||
.colour
|
|
||||||
.component_mul(&((diffuse + specular) * falloff));
|
|
||||||
colour += &intensity;
|
colour += &intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user