From 02a0740cac7feba5277cc3938023f4ca47ee7f49 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Fri, 1 Jul 2016 00:00:38 -0700 Subject: [PATCH] More proper use of light sources. --- src/color/mod.rs | 71 ++++++++++++++++++++++++++++++++++++++---- src/float4.rs | 16 ++++++++++ src/parse/psy_light.rs | 6 ++-- src/renderer.rs | 25 ++++++++------- 4 files changed, 97 insertions(+), 21 deletions(-) diff --git a/src/color/mod.rs b/src/color/mod.rs index 04fd54f..01685f4 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -2,6 +2,7 @@ mod spectra_xyz; use std::ops::{Add, AddAssign, Mul, MulAssign, Div, DivAssign}; +use float4::Float4; use lerp::Lerp; use self::spectra_xyz::{spectrum_xyz_to_p, EQUAL_ENERGY_REFLECTANCE}; @@ -20,10 +21,10 @@ pub trait Color { fn to_spectral_sample(&self, hero_wavelength: f32) -> SpectralSample { SpectralSample { - e: [self.sample_spectrum(nth_wavelength(hero_wavelength, 0)), - self.sample_spectrum(nth_wavelength(hero_wavelength, 1)), - self.sample_spectrum(nth_wavelength(hero_wavelength, 2)), - self.sample_spectrum(nth_wavelength(hero_wavelength, 3))], + e: Float4::new(self.sample_spectrum(nth_wavelength(hero_wavelength, 0)), + self.sample_spectrum(nth_wavelength(hero_wavelength, 1)), + self.sample_spectrum(nth_wavelength(hero_wavelength, 2)), + self.sample_spectrum(nth_wavelength(hero_wavelength, 3))), hero_wavelength: hero_wavelength, } @@ -42,7 +43,7 @@ fn nth_wavelength(hero_wavelength: f32, n: usize) -> f32 { #[derive(Copy, Clone, Debug)] pub struct SpectralSample { - e: [f32; 4], + e: Float4, hero_wavelength: f32, } @@ -50,7 +51,15 @@ impl SpectralSample { pub fn new(wavelength: f32) -> SpectralSample { debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX); SpectralSample { - e: [0.0; 4], + e: Float4::new(0.0, 0.0, 0.0, 0.0), + hero_wavelength: wavelength, + } + } + + pub fn from_value(value: f32, wavelength: f32) -> SpectralSample { + debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX); + SpectralSample { + e: Float4::new(value, value, value, value), hero_wavelength: wavelength, } } @@ -66,6 +75,56 @@ impl SpectralSample { } } +impl Add for SpectralSample { + type Output = SpectralSample; + fn add(self, rhs: SpectralSample) -> Self::Output { + assert!(self.hero_wavelength == rhs.hero_wavelength); + SpectralSample { + e: self.e + rhs.e, + hero_wavelength: self.hero_wavelength, + } + } +} + +impl AddAssign for SpectralSample { + fn add_assign(&mut self, rhs: SpectralSample) { + assert!(self.hero_wavelength == rhs.hero_wavelength); + self.e = self.e + rhs.e; + } +} + +impl Mul for SpectralSample { + type Output = SpectralSample; + fn mul(self, rhs: f32) -> Self::Output { + SpectralSample { + e: self.e * rhs, + hero_wavelength: self.hero_wavelength, + } + } +} + +impl MulAssign for SpectralSample { + fn mul_assign(&mut self, rhs: f32) { + self.e = self.e * rhs; + } +} + +impl Div for SpectralSample { + type Output = SpectralSample; + fn div(self, rhs: f32) -> Self::Output { + SpectralSample { + e: self.e / rhs, + hero_wavelength: self.hero_wavelength, + } + } +} + +impl DivAssign for SpectralSample { + fn div_assign(&mut self, rhs: f32) { + self.e = self.e / rhs; + } +} + #[derive(Copy, Clone, Debug)] pub struct XYZ { diff --git a/src/float4.rs b/src/float4.rs index 61acc8e..480dccb 100644 --- a/src/float4.rs +++ b/src/float4.rs @@ -88,6 +88,22 @@ impl Float4 { *self.data.get_unchecked_mut(3) = n; } } + + pub fn get_0(&self) -> f32 { + unsafe { *self.data.get_unchecked(0) } + } + + pub fn get_1(&self) -> f32 { + unsafe { *self.data.get_unchecked(1) } + } + + pub fn get_2(&self) -> f32 { + unsafe { *self.data.get_unchecked(2) } + } + + pub fn get_3(&self) -> f32 { + unsafe { *self.data.get_unchecked(3) } + } } diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs index d43086a..d686299 100644 --- a/src/parse/psy_light.rs +++ b/src/parse/psy_light.rs @@ -9,7 +9,7 @@ use super::basics::ws_f32; use super::psy::PsyParseError; use light::{SphereLight, RectangleLight}; -use color::XYZ; +use color::{XYZ, rec709e_to_xyz}; pub fn parse_sphere_light(tree: &DataTree) -> Result { if let &DataTree::Internal { ref children, .. } = tree { @@ -37,7 +37,7 @@ pub fn parse_sphere_light(tree: &DataTree) -> Result // TODO: handle color space conversions properly. // Probably will need a special color type with its // own parser...? - colors.push(XYZ::new(color.0, color.1, color.2)); + colors.push(XYZ::from_tuple(rec709e_to_xyz(color))); } else { // Found color, but its contents is not in the right format return Err(PsyParseError::UnknownError); @@ -81,7 +81,7 @@ pub fn parse_rectangle_light(tree: &DataTree) -> Result 0.0 { @@ -266,8 +268,8 @@ impl LightPath { nor.into_vector().normalized() }; let la = dot(rnor, shadow_vec.normalized()).max(0.0); - self.light_attenuation = XYZ::from_spectral_sample(&XYZ::new(la, la, la) - .to_spectral_sample(self.wavelength)); + // self.light_attenuation = SpectralSample::from_value(la); + self.pending_color_addition = light_color * la / light_pdf; *ray = Ray::new(pos + rnor * 0.0001, shadow_vec - rnor * 0.0001, self.time, @@ -280,8 +282,7 @@ impl LightPath { } else { // Didn't hit anything, so background color let xyz = XYZ::new(0.02, 0.02, 0.02); - self.color += - XYZ::from_spectral_sample(&xyz.to_spectral_sample(self.wavelength)); + self.color += xyz.to_spectral_sample(self.wavelength); return false; } @@ -291,7 +292,7 @@ impl LightPath { 1 => { self.round += 1; if let &surface::SurfaceIntersection::Miss = isect { - self.color += self.light_attenuation; + self.color += self.pending_color_addition; } return false; }