specular metallic materials
This commit is contained in:
parent
e1c61ef944
commit
1a355f81ca
15 changed files with 533 additions and 27 deletions
|
|
@ -5,6 +5,7 @@ mod geometry;
|
|||
mod ray;
|
||||
mod scene_data;
|
||||
mod colors;
|
||||
mod math_utils;
|
||||
|
||||
use std::string::String;
|
||||
use cgmath::Vector4;
|
||||
|
|
|
|||
37
src/math_utils.rs
Normal file
37
src/math_utils.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use std::f32::consts::PI;
|
||||
use cgmath::{InnerSpace, Vector3};
|
||||
use easy_gltf::model::Triangle;
|
||||
use crate::ray::Ray;
|
||||
|
||||
/// return a uniform random angle in the hemisphere specified by the triangle
|
||||
pub fn uniform_random_angle_triangle_hemisphere(intersected_triangle: Triangle, ray: &Ray) -> Vector3<f32> {
|
||||
let tangent = (intersected_triangle[0].position -
|
||||
intersected_triangle[1].position).normalize();
|
||||
let mut face_normal: Vector3<f32> = tangent
|
||||
.cross(intersected_triangle[0].position -
|
||||
intersected_triangle[2].position).normalize();
|
||||
//flip normal if face is hit from behind
|
||||
if face_normal.dot(-ray.direction) < 0.0 {
|
||||
face_normal *= -1.0;
|
||||
}
|
||||
let bitangent = tangent.cross(face_normal).normalize();
|
||||
/*
|
||||
generate random direction on hemisphere
|
||||
*/
|
||||
let phi = rand::random::<f32>() * 2.0 * PI;
|
||||
//allow arbitrary angles
|
||||
let radius = rand::random::<f32>();
|
||||
let sqrt_radius = f32::sqrt(rand::random::<f32>());
|
||||
|
||||
(tangent * f32::cos(phi) * sqrt_radius +
|
||||
bitangent * f32::sin(phi) * sqrt_radius +
|
||||
face_normal * f32::sqrt(1.0 - radius)).normalize()
|
||||
}
|
||||
|
||||
/// Calculate a triangle from the three Vertices
|
||||
pub fn face_normal_for_triangle(triangle: &Triangle) -> Vector3<f32> {
|
||||
let tangent = (triangle[0].position -
|
||||
triangle[1].position).normalize();
|
||||
tangent.cross(triangle[0].position -
|
||||
triangle[2].position).normalize()
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ use easy_gltf::{Camera, Projection, Scene};
|
|||
use indicatif::ParallelProgressIterator;
|
||||
use crate::Args;
|
||||
use crate::geometry::{Intersectable};
|
||||
use crate::math_utils::{face_normal_for_triangle, uniform_random_angle_triangle_hemisphere};
|
||||
use crate::ray::{construct_primary_rays, Ray};
|
||||
use crate::scene_data::IntersectionData;
|
||||
|
||||
|
|
@ -150,44 +151,47 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
|||
recursion_depth_left: usize) -> Vector4<f32> {
|
||||
let mut pixel_radiosity: Vector4<f32>
|
||||
= Vector4::new(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
//accumulate colors at point
|
||||
//emissive Component
|
||||
pixel_radiosity +=
|
||||
intersection_data.material().emissive.factor.extend(1.0)
|
||||
.mul_element_wise(
|
||||
intersection_data.material()
|
||||
//TODO: texture sampling!
|
||||
.get_base_color_alpha(Vector2::new(0.0, 0.0))
|
||||
);
|
||||
|
||||
|
||||
//get the intersected triangle and calculate the face normals
|
||||
let intersected_triangle = intersection_data.intersected_triangle();
|
||||
let tangent = (intersected_triangle[0].position -
|
||||
intersected_triangle[1].position).normalize();
|
||||
let mut face_normal: Vector3<f32> = tangent
|
||||
.cross(intersected_triangle[0].position -
|
||||
intersected_triangle[2].position).normalize();
|
||||
//flip normal if face is hit from behind
|
||||
if face_normal.dot(-intersection_data.ray().direction) < 0.0 {
|
||||
face_normal *= -1.0;
|
||||
|
||||
let decision_factor = rand::random::<f32>();
|
||||
let mut direction: Vector3<f32>;
|
||||
|
||||
let face_normal =
|
||||
face_normal_for_triangle(&intersection_data.intersected_triangle());
|
||||
|
||||
let rough_sampling: bool = decision_factor <= intersection_data.material().pbr.roughness_factor;
|
||||
|
||||
//do we trace rough or specular?
|
||||
if rough_sampling {
|
||||
//generate random direction (rough sampling)
|
||||
direction = uniform_random_angle_triangle_hemisphere(
|
||||
intersected_triangle,
|
||||
intersection_data.ray(),
|
||||
);
|
||||
} else {
|
||||
//mirror vector (specular sampling)
|
||||
direction = intersection_data.ray().direction -
|
||||
2.0 * (intersection_data.ray().direction.dot(face_normal)) * face_normal;
|
||||
}
|
||||
let bitangent = tangent.cross(face_normal).normalize();
|
||||
|
||||
/*
|
||||
generate random direction on hemisphere
|
||||
*/
|
||||
let phi = rand::random::<f32>() * 2.0 * PI;
|
||||
//allow arbitrary angles
|
||||
let radius = rand::random::<f32>();
|
||||
let sqrt_radius = f32::sqrt(rand::random::<f32>());
|
||||
|
||||
let direction = (tangent * f32::cos(phi) * sqrt_radius +
|
||||
bitangent * f32::sin(phi) * sqrt_radius +
|
||||
face_normal * f32::sqrt(1.0 - radius)).normalize();
|
||||
direction = direction.normalize();
|
||||
|
||||
let secondary_ray = Ray {
|
||||
//prevent self-intersection
|
||||
source: intersection_data.intersection_point() + RAY_EPSILON * face_normal,
|
||||
source: intersection_data.intersection_point() + RAY_EPSILON * direction,
|
||||
direction,
|
||||
};
|
||||
|
||||
|
|
@ -197,15 +201,27 @@ fn accumulate_colors(intersection_data: &IntersectionData,
|
|||
global_scene,
|
||||
recursion_depth_left - 1);
|
||||
|
||||
//weigh by cosine term depending on view angel
|
||||
let cos_weighting = direction.dot(
|
||||
face_normal
|
||||
);
|
||||
|
||||
let cos_weighting = direction.dot(face_normal);
|
||||
let brdf: Vector4<f32>;
|
||||
|
||||
let brdf = intersection_data.material()
|
||||
.get_base_color_alpha(Vector2::new(0.0, 0.0));
|
||||
|
||||
//reflected component
|
||||
pixel_radiosity += brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI;
|
||||
if rough_sampling {
|
||||
brdf = intersection_data.material()
|
||||
//TODO: texture sampling!
|
||||
.get_base_color_alpha(Vector2::new(0.0, 0.0));
|
||||
pixel_radiosity += brdf.mul_element_wise(incoming_radiosity) * cos_weighting * 2.0 * PI;
|
||||
} else {
|
||||
pixel_radiosity += incoming_radiosity * cos_weighting * 2.0 * PI +
|
||||
intersection_data.material()
|
||||
//TODO: texture sampling!
|
||||
.get_base_color_alpha(Vector2::new(0.0, 0.0));
|
||||
}
|
||||
|
||||
pixel_radiosity
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue