Laying some groundwork for a simple shading system.
This commit is contained in:
parent
114f11c583
commit
4a86c4122a
|
@ -81,7 +81,7 @@ pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sphere Light
|
// Rectangle Light
|
||||||
"RectangleLight" => {
|
"RectangleLight" => {
|
||||||
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
builder.add_object(ident,
|
builder.add_object(ident,
|
||||||
|
@ -92,6 +92,17 @@ pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Surface shader
|
||||||
|
"SurfaceShader" => {
|
||||||
|
if let &DataTree::Internal { ident: Some(ident), .. } = child {
|
||||||
|
// TODO
|
||||||
|
unimplemented!()
|
||||||
|
} else {
|
||||||
|
// TODO: error condition of some kind, because no ident
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
// TODO: some kind of error, because not a known type name
|
// TODO: some kind of error, because not a known type name
|
||||||
}
|
}
|
||||||
|
@ -121,12 +132,6 @@ pub fn parse_assembly(tree: &DataTree) -> Result<Assembly, PsyParseError> {
|
||||||
// assembly->add_surface_shader(child.name, parse_surface_shader(child));
|
// assembly->add_surface_shader(child.name, parse_surface_shader(child));
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// // Rectangle Light
|
|
||||||
// else if (child.type == "RectangleLight") {
|
|
||||||
// assembly->add_object(child.name, parse_rectangle_light(child));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -286,12 +286,8 @@ impl LightPath {
|
||||||
|
|
||||||
// Result of shading ray, prepare light ray
|
// Result of shading ray, prepare light ray
|
||||||
if self.round % 2 == 1 {
|
if self.round % 2 == 1 {
|
||||||
if let &surface::SurfaceIntersection::Hit { t: _,
|
if let &surface::SurfaceIntersection::Hit { intersection_data: idata, closure } =
|
||||||
incoming: _,
|
isect {
|
||||||
pos,
|
|
||||||
nor,
|
|
||||||
local_space: _,
|
|
||||||
closure } = isect {
|
|
||||||
// Hit something! Do the stuff
|
// Hit something! Do the stuff
|
||||||
self.interaction = *isect; // Store interaction for use in next phase
|
self.interaction = *isect; // Store interaction for use in next phase
|
||||||
|
|
||||||
|
@ -310,7 +306,7 @@ impl LightPath {
|
||||||
// to the film plane if the light is not in shadow.
|
// to the film plane if the light is not in shadow.
|
||||||
self.pending_color_addition = {
|
self.pending_color_addition = {
|
||||||
let material = closure.as_surface_closure();
|
let material = closure.as_surface_closure();
|
||||||
let la = material.evaluate(ray.dir, shadow_vec, nor, self.wavelength);
|
let la = material.evaluate(ray.dir, shadow_vec, idata.nor, self.wavelength);
|
||||||
light_color * la * self.light_attenuation / (light_pdf * light_sel_pdf)
|
light_color * la * self.light_attenuation / (light_pdf * light_sel_pdf)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -318,7 +314,7 @@ impl LightPath {
|
||||||
// in shadow or not.
|
// in shadow or not.
|
||||||
// TODO: use proper ray offsets for avoiding self-shadowing
|
// TODO: use proper ray offsets for avoiding self-shadowing
|
||||||
// rather than this hacky stupid stuff.
|
// rather than this hacky stupid stuff.
|
||||||
*ray = Ray::new(pos + shadow_vec.normalized() * 0.001,
|
*ray = Ray::new(idata.pos + shadow_vec.normalized() * 0.001,
|
||||||
shadow_vec,
|
shadow_vec,
|
||||||
self.time,
|
self.time,
|
||||||
true);
|
true);
|
||||||
|
@ -349,18 +345,14 @@ impl LightPath {
|
||||||
|
|
||||||
// Calculate bounced lighting!
|
// Calculate bounced lighting!
|
||||||
if self.round < 6 {
|
if self.round < 6 {
|
||||||
if let surface::SurfaceIntersection::Hit { t: _,
|
if let surface::SurfaceIntersection::Hit { intersection_data: idata, closure } =
|
||||||
pos,
|
self.interaction {
|
||||||
incoming,
|
|
||||||
nor,
|
|
||||||
local_space: _,
|
|
||||||
closure } = self.interaction {
|
|
||||||
// Sample material
|
// Sample material
|
||||||
let (dir, filter, pdf) = {
|
let (dir, filter, pdf) = {
|
||||||
let material = closure.as_surface_closure();
|
let material = closure.as_surface_closure();
|
||||||
let u = self.next_lds_samp();
|
let u = self.next_lds_samp();
|
||||||
let v = self.next_lds_samp();
|
let v = self.next_lds_samp();
|
||||||
material.sample(incoming, nor, (u, v), self.wavelength)
|
material.sample(idata.incoming, idata.nor, (u, v), self.wavelength)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Account for the additional light attenuation from
|
// Account for the additional light attenuation from
|
||||||
|
@ -368,7 +360,7 @@ impl LightPath {
|
||||||
self.light_attenuation *= filter / pdf;
|
self.light_attenuation *= filter / pdf;
|
||||||
|
|
||||||
// Calculate the ray for this bounce
|
// Calculate the ray for this bounce
|
||||||
*ray = Ray::new(pos + dir.normalized() * 0.0001, dir, self.time, false);
|
*ray = Ray::new(idata.pos + dir.normalized() * 0.0001, dir, self.time, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl Assembly {
|
||||||
time: f32,
|
time: f32,
|
||||||
intr: &SurfaceIntersection)
|
intr: &SurfaceIntersection)
|
||||||
-> Option<(SpectralSample, Vector, f32, f32)> {
|
-> Option<(SpectralSample, Vector, f32, f32)> {
|
||||||
if let &SurfaceIntersection::Hit { pos, incoming, nor, closure, .. } = intr {
|
if let &SurfaceIntersection::Hit { intersection_data: idata, closure } = intr {
|
||||||
let sel_xform = if xform_stack.top().len() > 0 {
|
let sel_xform = if xform_stack.top().len() > 0 {
|
||||||
lerp_slice(xform_stack.top(), time)
|
lerp_slice(xform_stack.top(), time)
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,9 +50,9 @@ impl Assembly {
|
||||||
};
|
};
|
||||||
if let Some((light_i, sel_pdf, whittled_n)) =
|
if let Some((light_i, sel_pdf, whittled_n)) =
|
||||||
self.light_accel
|
self.light_accel
|
||||||
.select(incoming * sel_xform,
|
.select(idata.incoming * sel_xform,
|
||||||
pos * sel_xform,
|
idata.pos * sel_xform,
|
||||||
nor * sel_xform,
|
idata.nor * sel_xform,
|
||||||
closure.as_surface_closure(),
|
closure.as_surface_closure(),
|
||||||
time,
|
time,
|
||||||
n) {
|
n) {
|
||||||
|
@ -82,7 +82,7 @@ impl Assembly {
|
||||||
|
|
||||||
// Sample the light
|
// Sample the light
|
||||||
let (color, shadow_vec, pdf) =
|
let (color, shadow_vec, pdf) =
|
||||||
light.sample(&xform, pos, uvw.0, uvw.1, wavelength, time);
|
light.sample(&xform, idata.pos, uvw.0, uvw.1, wavelength, time);
|
||||||
return Some((color, shadow_vec, pdf, sel_pdf));
|
return Some((color, shadow_vec, pdf, sel_pdf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1,41 @@
|
||||||
pub mod surface_closure;
|
pub mod surface_closure;
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use self::surface_closure::SurfaceClosureUnion;
|
||||||
|
use surface::SurfaceIntersectionData;
|
||||||
|
|
||||||
|
/// Trait for surface shaders.
|
||||||
|
pub trait SurfaceShader: Debug {
|
||||||
|
/// Takes the result of a surface intersection and returns the surface
|
||||||
|
/// closure to be evaluated at that intersection point.
|
||||||
|
fn shade(&self, data: &SurfaceIntersectionData) -> SurfaceClosureUnion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clearly we must eat this brownie before the world ends, lest it
|
||||||
|
/// go uneaten before the world ends. But to do so we must trek
|
||||||
|
/// far--much like in Lord of the Rings--to fetch the golden fork with
|
||||||
|
/// which to eat the brownie. Only this fork can be used to eat this
|
||||||
|
/// brownie, for any who try to eat it with a normal fork shall
|
||||||
|
/// perish immediately and without honor. But guarding the fork are
|
||||||
|
/// three large donuts, which must all be eaten in sixty seconds or
|
||||||
|
/// less to continue on. It's called the donut challenge. But these
|
||||||
|
/// are no ordinary donuts. To call them large is actually doing
|
||||||
|
/// them a great injustice, for they are each the size of a small
|
||||||
|
/// building.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SimpleSurfaceShader {
|
||||||
|
closure: SurfaceClosureUnion,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimpleSurfaceShader {
|
||||||
|
fn new(closure: SurfaceClosureUnion) -> SimpleSurfaceShader {
|
||||||
|
SimpleSurfaceShader { closure: closure }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceShader for SimpleSurfaceShader {
|
||||||
|
fn shade(&self, data: &SurfaceIntersectionData) -> SurfaceClosureUnion {
|
||||||
|
self.closure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,20 +11,6 @@ use ray::{Ray, AccelRay};
|
||||||
use shading::surface_closure::SurfaceClosureUnion;
|
use shading::surface_closure::SurfaceClosureUnion;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum SurfaceIntersection {
|
|
||||||
Miss,
|
|
||||||
Occlude,
|
|
||||||
Hit {
|
|
||||||
t: f32,
|
|
||||||
pos: Point,
|
|
||||||
incoming: Vector,
|
|
||||||
nor: Normal,
|
|
||||||
local_space: Matrix4x4,
|
|
||||||
closure: SurfaceClosureUnion,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Surface: Boundable + Debug + Sync {
|
pub trait Surface: Boundable + Debug + Sync {
|
||||||
fn intersect_rays(&self,
|
fn intersect_rays(&self,
|
||||||
accel_rays: &mut [AccelRay],
|
accel_rays: &mut [AccelRay],
|
||||||
|
@ -32,3 +18,26 @@ pub trait Surface: Boundable + Debug + Sync {
|
||||||
isects: &mut [SurfaceIntersection],
|
isects: &mut [SurfaceIntersection],
|
||||||
space: &[Matrix4x4]);
|
space: &[Matrix4x4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum SurfaceIntersection {
|
||||||
|
Miss,
|
||||||
|
Occlude,
|
||||||
|
Hit {
|
||||||
|
intersection_data: SurfaceIntersectionData,
|
||||||
|
closure: SurfaceClosureUnion,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct SurfaceIntersectionData {
|
||||||
|
pub incoming: Vector, // Direction of the incoming ray
|
||||||
|
pub t: f32, // Ray t-value at the intersection point
|
||||||
|
pub pos: Point, // Position of the intersection
|
||||||
|
pub nor: Normal, // Shading normal
|
||||||
|
pub nor_g: Normal, // True geometric normal
|
||||||
|
pub uv: (f32, f32), // 2d surface parameters
|
||||||
|
pub local_space: Matrix4x4, // Matrix from global space to local space
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use math::{Point, Matrix4x4, cross};
|
||||||
use ray::{Ray, AccelRay};
|
use ray::{Ray, AccelRay};
|
||||||
use shading::surface_closure::{SurfaceClosureUnion, GTRClosure};
|
use shading::surface_closure::{SurfaceClosureUnion, GTRClosure};
|
||||||
|
|
||||||
use super::{Surface, SurfaceIntersection};
|
use super::{Surface, SurfaceIntersection, SurfaceIntersectionData};
|
||||||
use super::triangle;
|
use super::triangle;
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,11 +92,15 @@ impl Surface for TriangleMesh {
|
||||||
r.mark_done();
|
r.mark_done();
|
||||||
} else {
|
} else {
|
||||||
isects[r.id as usize] = SurfaceIntersection::Hit {
|
isects[r.id as usize] = SurfaceIntersection::Hit {
|
||||||
|
intersection_data: SurfaceIntersectionData {
|
||||||
|
incoming: wr.dir,
|
||||||
t: t,
|
t: t,
|
||||||
pos: wr.orig + (wr.dir * t),
|
pos: wr.orig + (wr.dir * t),
|
||||||
incoming: wr.dir,
|
nor: cross(tri.0 - tri.1, tri.0 - tri.2).into_normal(), // TODO
|
||||||
nor: cross(tri.0 - tri.1, tri.0 - tri.2).into_normal(),
|
nor_g: cross(tri.0 - tri.1, tri.0 - tri.2).into_normal(),
|
||||||
|
uv: (0.0, 0.0), // TODO
|
||||||
local_space: mat_space,
|
local_space: mat_space,
|
||||||
|
},
|
||||||
// TODO: get surface closure from surface shader.
|
// TODO: get surface closure from surface shader.
|
||||||
//closure: SurfaceClosureUnion::LambertClosure(
|
//closure: SurfaceClosureUnion::LambertClosure(
|
||||||
// LambertClosure::new(XYZ::new(0.8, 0.8, 0.8))
|
// LambertClosure::new(XYZ::new(0.8, 0.8, 0.8))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user