Implement interpolation of surface closures between micropoly vertices.

This commit is contained in:
Nathan Vegdahl 2020-03-24 11:10:18 +09:00
parent 946a1860e0
commit 80f9c3cc2d
5 changed files with 154 additions and 38 deletions

View File

@ -1,5 +1,3 @@
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign};
pub use color::{ pub use color::{
rec709_e_to_xyz, rec709_to_xyz, xyz_to_aces_ap0, xyz_to_aces_ap0_e, xyz_to_rec709, rec709_e_to_xyz, rec709_to_xyz, xyz_to_aces_ap0, xyz_to_aces_ap0_e, xyz_to_rec709,
xyz_to_rec709_e, xyz_to_rec709_e,
@ -249,12 +247,8 @@ impl Color {
_ => unreachable!(), _ => unreachable!(),
} }
} }
}
impl Mul<f32> for Color { pub fn scale_brightness(self, rhs: f32) -> Self {
type Output = Self;
fn mul(self, rhs: f32) -> Self {
match self { match self {
Color::XYZ(x, y, z) => Color::XYZ(x * rhs, y * rhs, z * rhs), Color::XYZ(x, y, z) => Color::XYZ(x * rhs, y * rhs, z * rhs),
@ -277,9 +271,75 @@ impl Mul<f32> for Color {
} }
} }
impl MulAssign<f32> for Color { // Implemented for interpolation operations, not for any otherwise meaningful
fn mul_assign(&mut self, rhs: f32) { // notion of addition.
*self = *self * rhs; impl std::ops::Add<Color> for Color {
type Output = Self;
fn add(self, rhs: Self) -> Self {
match (self, rhs) {
(Color::XYZ(x1, y1, z1), Color::XYZ(x2, y2, z2)) => {
Color::XYZ(x1 + x2, y1 + y2, z1 + z2)
}
(
Color::Blackbody {
temperature: tmp1,
factor: fac1,
},
Color::Blackbody {
temperature: tmp2,
factor: fac2,
},
) => Color::Blackbody {
temperature: tmp1 + tmp2,
factor: fac1 + fac2,
},
(
Color::Temperature {
temperature: tmp1,
factor: fac1,
},
Color::Temperature {
temperature: tmp2,
factor: fac2,
},
) => Color::Temperature {
temperature: tmp1 + tmp2,
factor: fac1 + fac2,
},
_ => panic!("Cannot add colors with different representations."),
}
}
}
// Implemented for interpolation operations, not for any otherwise meaningful
// notion of multiplication.
impl std::ops::Mul<f32> for Color {
type Output = Self;
fn mul(self, rhs: f32) -> Self {
match self {
Color::XYZ(x, y, z) => Color::XYZ(x * rhs, y * rhs, z * rhs),
Color::Blackbody {
temperature,
factor,
} => Color::Blackbody {
temperature: temperature * rhs,
factor: factor * rhs,
},
Color::Temperature {
temperature,
factor,
} => Color::Temperature {
temperature: temperature * rhs,
factor: factor * rhs,
},
}
} }
} }
@ -429,7 +489,7 @@ impl SpectralSample {
} }
} }
impl Add for SpectralSample { impl std::ops::Add for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn add(self, rhs: SpectralSample) -> Self::Output { fn add(self, rhs: SpectralSample) -> Self::Output {
assert_eq!(self.hero_wavelength, rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
@ -440,14 +500,14 @@ impl Add for SpectralSample {
} }
} }
impl AddAssign for SpectralSample { impl std::ops::AddAssign for SpectralSample {
fn add_assign(&mut self, rhs: SpectralSample) { fn add_assign(&mut self, rhs: SpectralSample) {
assert_eq!(self.hero_wavelength, rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
self.e = self.e + rhs.e; self.e = self.e + rhs.e;
} }
} }
impl Mul for SpectralSample { impl std::ops::Mul for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn mul(self, rhs: SpectralSample) -> Self::Output { fn mul(self, rhs: SpectralSample) -> Self::Output {
assert_eq!(self.hero_wavelength, rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
@ -458,14 +518,14 @@ impl Mul for SpectralSample {
} }
} }
impl MulAssign for SpectralSample { impl std::ops::MulAssign for SpectralSample {
fn mul_assign(&mut self, rhs: SpectralSample) { fn mul_assign(&mut self, rhs: SpectralSample) {
assert_eq!(self.hero_wavelength, rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
self.e = self.e * rhs.e; self.e = self.e * rhs.e;
} }
} }
impl Mul<f32> for SpectralSample { impl std::ops::Mul<f32> for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn mul(self, rhs: f32) -> Self::Output { fn mul(self, rhs: f32) -> Self::Output {
SpectralSample { SpectralSample {
@ -475,13 +535,13 @@ impl Mul<f32> for SpectralSample {
} }
} }
impl MulAssign<f32> for SpectralSample { impl std::ops::MulAssign<f32> for SpectralSample {
fn mul_assign(&mut self, rhs: f32) { fn mul_assign(&mut self, rhs: f32) {
self.e = self.e * rhs; self.e = self.e * rhs;
} }
} }
impl Div<f32> for SpectralSample { impl std::ops::Div<f32> for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn div(self, rhs: f32) -> Self::Output { fn div(self, rhs: f32) -> Self::Output {
SpectralSample { SpectralSample {
@ -491,7 +551,7 @@ impl Div<f32> for SpectralSample {
} }
} }
impl DivAssign<f32> for SpectralSample { impl std::ops::DivAssign<f32> for SpectralSample {
fn div_assign(&mut self, rhs: f32) { fn div_assign(&mut self, rhs: f32) {
self.e = self.e / rhs; self.e = self.e / rhs;
} }
@ -538,7 +598,7 @@ impl Lerp for XYZ {
} }
} }
impl Add for XYZ { impl std::ops::Add for XYZ {
type Output = XYZ; type Output = XYZ;
fn add(self, rhs: XYZ) -> Self::Output { fn add(self, rhs: XYZ) -> Self::Output {
XYZ { XYZ {
@ -549,7 +609,7 @@ impl Add for XYZ {
} }
} }
impl AddAssign for XYZ { impl std::ops::AddAssign for XYZ {
fn add_assign(&mut self, rhs: XYZ) { fn add_assign(&mut self, rhs: XYZ) {
self.x += rhs.x; self.x += rhs.x;
self.y += rhs.y; self.y += rhs.y;
@ -557,7 +617,7 @@ impl AddAssign for XYZ {
} }
} }
impl Mul<f32> for XYZ { impl std::ops::Mul<f32> for XYZ {
type Output = XYZ; type Output = XYZ;
fn mul(self, rhs: f32) -> Self::Output { fn mul(self, rhs: f32) -> Self::Output {
XYZ { XYZ {
@ -568,7 +628,7 @@ impl Mul<f32> for XYZ {
} }
} }
impl MulAssign<f32> for XYZ { impl std::ops::MulAssign<f32> for XYZ {
fn mul_assign(&mut self, rhs: f32) { fn mul_assign(&mut self, rhs: f32) {
self.x *= rhs; self.x *= rhs;
self.y *= rhs; self.y *= rhs;
@ -576,7 +636,7 @@ impl MulAssign<f32> for XYZ {
} }
} }
impl Div<f32> for XYZ { impl std::ops::Div<f32> for XYZ {
type Output = XYZ; type Output = XYZ;
fn div(self, rhs: f32) -> Self::Output { fn div(self, rhs: f32) -> Self::Output {
XYZ { XYZ {
@ -587,7 +647,7 @@ impl Div<f32> for XYZ {
} }
} }
impl DivAssign<f32> for XYZ { impl std::ops::DivAssign<f32> for XYZ {
fn div_assign(&mut self, rhs: f32) { fn div_assign(&mut self, rhs: f32) {
self.x /= rhs; self.x /= rhs;
self.y /= rhs; self.y /= rhs;

View File

@ -315,7 +315,8 @@ impl<'a> Surface for RectangleLight<'a> {
let closure = { let closure = {
let inv_surface_area = (1.0 / (dim.0 as f64 * dim.1 as f64)) as f32; let inv_surface_area = (1.0 / (dim.0 as f64 * dim.1 as f64)) as f32;
let color = lerp_slice(self.colors, time) * inv_surface_area; let color = lerp_slice(self.colors, time)
.scale_brightness(inv_surface_area);
SurfaceClosure::Emit(color) SurfaceClosure::Emit(color)
}; };

View File

@ -321,7 +321,7 @@ impl<'a> Surface for SphereLight<'a> {
let closure = { let closure = {
let inv_surface_area = let inv_surface_area =
(1.0 / (4.0 * PI_64 * radius as f64 * radius as f64)) as f32; (1.0 / (4.0 * PI_64 * radius as f64 * radius as f64)) as f32;
let color = lerp_slice(self.colors, time) * inv_surface_area; let color = lerp_slice(self.colors, time).scale_brightness(inv_surface_area);
SurfaceClosure::Emit(color) SurfaceClosure::Emit(color)
}; };

View File

@ -250,6 +250,59 @@ impl SurfaceClosure {
} }
} }
// Implemented for interpolation operations, not for any otherwise meaningful
// notion of addition.
impl std::ops::Add<SurfaceClosure> for SurfaceClosure {
type Output = Self;
fn add(self, rhs: Self) -> Self {
match (self, rhs) {
(Lambert(col1), Lambert(col2)) => Lambert(col1 + col2),
(
GGX {
color: col1,
roughness: rgh1,
fresnel: frs1,
},
GGX {
color: col2,
roughness: rgh2,
fresnel: frs2,
},
) => GGX {
color: col1 + col2,
roughness: rgh1 + rgh2,
fresnel: frs1 + frs2,
},
(Emit(col1), Emit(col2)) => Emit(col1 + col2),
_ => panic!("Cannot add two different surface closure types."),
}
}
}
// Implemented for interpolation operations, not for any otherwise meaningful
// notion of multiplication.
impl std::ops::Mul<f32> for SurfaceClosure {
type Output = Self;
fn mul(self, rhs: f32) -> Self {
match self {
Lambert(col) => Lambert(col * rhs),
GGX {
color: col,
roughness: rgh,
fresnel: frs,
} => GGX {
color: col * rhs,
roughness: rgh * rhs,
fresnel: frs * rhs,
},
Emit(col) => Emit(col * rhs),
}
}
}
impl Lerp for SurfaceClosure { impl Lerp for SurfaceClosure {
fn lerp(self, other: SurfaceClosure, alpha: f32) -> SurfaceClosure { fn lerp(self, other: SurfaceClosure, alpha: f32) -> SurfaceClosure {
match (self, other) { match (self, other) {

View File

@ -33,9 +33,9 @@ pub struct MicropolyBatch<'a> {
normals: &'a [Normal], normals: &'a [Normal],
// Per-vertex shading data. // Per-vertex shading data.
// TODO: time samples.
compressed_vertex_closure_size: usize, // Size in bites of a single compressed closure compressed_vertex_closure_size: usize, // Size in bites of a single compressed closure
vertex_closure_time_sample_count: usize, compressed_vertex_closures: &'a [u8], // Packed compressed closures
compressed_vertex_closures: &'a [u8], // Packed compressed closures
// Micro-triangle indices. Each element of the tuple specifies the index // Micro-triangle indices. Each element of the tuple specifies the index
// of a vertex, which indexes into all of the arrays above. // of a vertex, which indexes into all of the arrays above.
@ -130,7 +130,6 @@ impl<'a> MicropolyBatch<'a> {
vertices: vertices, vertices: vertices,
normals: normals, normals: normals,
compressed_vertex_closure_size: 0, compressed_vertex_closure_size: 0,
vertex_closure_time_sample_count: 1,
compressed_vertex_closures: &[], compressed_vertex_closures: &[],
indices: indices, indices: indices,
accel: accel, accel: accel,
@ -320,16 +319,19 @@ impl<'a> MicropolyBatch<'a> {
}; };
// Calculate interpolated surface closure. // Calculate interpolated surface closure.
// TODO: actually interpolate. // TODO: time sampling.
let closure = { let closure = {
let start_byte = hit_tri_indices.0 as usize let get_closure = |index| {
* self.compressed_vertex_closure_size let start_byte = index * self.compressed_vertex_closure_size;
* self.vertex_closure_time_sample_count; SurfaceClosure::from_compressed(
let end_byte = start_byte + self.compressed_vertex_closure_size; &self.compressed_vertex_closures[start_byte..],
let (closure, _) = SurfaceClosure::from_compressed( )
&self.compressed_vertex_closures[start_byte..end_byte], .0
); };
closure let c0 = get_closure(hit_tri_indices.0 as usize);
let c1 = get_closure(hit_tri_indices.1 as usize);
let c2 = get_closure(hit_tri_indices.2 as usize);
(c0 * b0) + (c1 * b1) + (c2 * b2)
}; };
let intersection_data = SurfaceIntersectionData { let intersection_data = SurfaceIntersectionData {