Implement interpolation of surface closures between micropoly vertices.
This commit is contained in:
parent
946a1860e0
commit
80f9c3cc2d
108
src/color.rs
108
src/color.rs
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user