Switched from in-tree float4 lib to glam.
This commit is contained in:
parent
5c5a01ecee
commit
88e7365bc4
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -8,6 +8,14 @@ dependencies = [
|
|||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.11"
|
||||
|
@ -110,10 +118,6 @@ name = "crossbeam"
|
|||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "float4"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.6"
|
||||
|
@ -124,6 +128,14 @@ name = "fuchsia-cprng"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/bitshifter/glam-rs.git?rev=0f314f99#0f314f990710ff9357e5896de2b55ec82fe88e0d"
|
||||
dependencies = [
|
||||
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.3.0"
|
||||
|
@ -147,7 +159,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "math3d"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"float4 0.1.0",
|
||||
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glam 0.7.1 (git+https://github.com/bitshifter/glam-rs.git?rev=0f314f99)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -246,7 +259,7 @@ dependencies = [
|
|||
"color 0.1.0",
|
||||
"copy_in_place 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"float4 0.1.0",
|
||||
"glam 0.7.1 (git+https://github.com/bitshifter/glam-rs.git?rev=0f314f99)",
|
||||
"half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"halton 0.1.0",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -449,7 +462,7 @@ version = "0.1.0"
|
|||
name = "spectral_upsampling"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"float4 0.1.0",
|
||||
"glam 0.7.1 (git+https://github.com/bitshifter/glam-rs.git?rev=0f314f99)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -551,6 +564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
|
||||
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
|
||||
|
@ -567,6 +581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum glam 0.7.1 (git+https://github.com/bitshifter/glam-rs.git?rev=0f314f99)" = "<none>"
|
||||
"checksum half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9353c2a89d550b58fa0061d8ed8d002a7d8cdf2494eb0e432859bd3a9e543836"
|
||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||
"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
members = [
|
||||
"sub_crates/bvh_order",
|
||||
"sub_crates/color",
|
||||
"sub_crates/float4",
|
||||
"sub_crates/halton",
|
||||
"sub_crates/math3d",
|
||||
"sub_crates/mem_arena",
|
||||
|
@ -36,6 +35,7 @@ png_encode_mini = "0.1.2"
|
|||
rustc-serialize = "0.3"
|
||||
scoped_threadpool = "0.1"
|
||||
time = "0.1"
|
||||
glam = {git="https://github.com/bitshifter/glam-rs.git", rev="0f314f99", default-features=false, features=["approx"]}
|
||||
|
||||
# Local crate dependencies
|
||||
[dependencies.bvh_order]
|
||||
|
@ -44,9 +44,6 @@ path = "sub_crates/bvh_order"
|
|||
[dependencies.color]
|
||||
path = "sub_crates/color"
|
||||
|
||||
[dependencies.float4]
|
||||
path = "sub_crates/float4"
|
||||
|
||||
[dependencies.halton]
|
||||
path = "sub_crates/halton"
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
use std::mem::{transmute, MaybeUninit};
|
||||
|
||||
use glam::Vec4Mask;
|
||||
|
||||
use mem_arena::MemArena;
|
||||
|
||||
use crate::{
|
||||
|
@ -23,7 +25,6 @@ use super::{
|
|||
};
|
||||
|
||||
use bvh_order::{calc_traversal_code, SplitAxes, TRAVERSAL_TABLE};
|
||||
use float4::Bool4;
|
||||
|
||||
pub fn ray_code(dir: Vector) -> usize {
|
||||
let ray_sign_is_neg = [dir.x() < 0.0, dir.y() < 0.0, dir.z() < 0.0];
|
||||
|
@ -122,12 +123,12 @@ impl<'a> BVH4<'a> {
|
|||
traversal_code,
|
||||
} => {
|
||||
node_tests += ray_stack.ray_count_in_next_task() as u64;
|
||||
let mut all_hits = Bool4::new_false();
|
||||
let mut all_hits = Vec4Mask::default();
|
||||
|
||||
// Ray testing
|
||||
ray_stack.pop_do_next_task_and_push_rays(children.len(), |ray_idx| {
|
||||
if rays.is_done(ray_idx) {
|
||||
Bool4::new_false()
|
||||
Vec4Mask::default()
|
||||
} else {
|
||||
let hits = if bounds.len() == 1 {
|
||||
bounds[0].intersect_ray(
|
||||
|
@ -148,7 +149,7 @@ impl<'a> BVH4<'a> {
|
|||
});
|
||||
|
||||
// If there were any intersections, create tasks.
|
||||
if !all_hits.is_all_false() {
|
||||
if all_hits.any() {
|
||||
let order_code = traversal_table[traversal_code as usize];
|
||||
let mut lane_count = 0;
|
||||
let mut i = children.len() as u8;
|
||||
|
|
20
src/bbox.rs
20
src/bbox.rs
|
@ -45,12 +45,12 @@ impl BBox {
|
|||
let t2 = (self.max.co - orig.co) * dir_inv.co;
|
||||
|
||||
// Find the far and near intersection
|
||||
let mut far_t = t1.v_max(t2);
|
||||
let mut near_t = t1.v_min(t2);
|
||||
far_t.set_3(std::f32::INFINITY);
|
||||
near_t.set_3(0.0);
|
||||
let far_hit_t = fast_minf32(far_t.h_min() * BBOX_MAXT_ADJUST, max_t);
|
||||
let near_hit_t = near_t.h_max();
|
||||
let mut far_t = t1.max(t2);
|
||||
let mut near_t = t1.min(t2);
|
||||
far_t.set_w(std::f32::INFINITY);
|
||||
near_t.set_w(0.0);
|
||||
let far_hit_t = fast_minf32(far_t.min_element() * BBOX_MAXT_ADJUST, max_t);
|
||||
let near_hit_t = near_t.max_element();
|
||||
|
||||
// Did we hit?
|
||||
near_hit_t <= far_hit_t
|
||||
|
@ -106,10 +106,10 @@ impl BitOr for BBox {
|
|||
fn bitor(self, rhs: BBox) -> BBox {
|
||||
BBox::from_points(
|
||||
Point {
|
||||
co: self.min.co.v_min(rhs.min.co),
|
||||
co: self.min.co.min(rhs.min.co),
|
||||
},
|
||||
Point {
|
||||
co: self.max.co.v_max(rhs.max.co),
|
||||
co: self.max.co.max(rhs.max.co),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -128,10 +128,10 @@ impl BitOr<Point> for BBox {
|
|||
fn bitor(self, rhs: Point) -> BBox {
|
||||
BBox::from_points(
|
||||
Point {
|
||||
co: self.min.co.v_min(rhs.co),
|
||||
co: self.min.co.min(rhs.co),
|
||||
},
|
||||
Point {
|
||||
co: self.max.co.v_max(rhs.co),
|
||||
co: self.max.co.max(rhs.co),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
75
src/bbox4.rs
75
src/bbox4.rs
|
@ -9,16 +9,16 @@ use crate::{
|
|||
math::{Point, Vector},
|
||||
};
|
||||
|
||||
use float4::{Bool4, Float4};
|
||||
use glam::{Vec4, Vec4Mask};
|
||||
|
||||
const BBOX_MAXT_ADJUST: f32 = 1.00000024;
|
||||
|
||||
/// A SIMD set of 4 3D axis-aligned bounding boxes.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BBox4 {
|
||||
pub x: (Float4, Float4), // (min, max)
|
||||
pub y: (Float4, Float4), // (min, max)
|
||||
pub z: (Float4, Float4), // (min, max)
|
||||
pub x: (Vec4, Vec4), // (min, max)
|
||||
pub y: (Vec4, Vec4), // (min, max)
|
||||
pub z: (Vec4, Vec4), // (min, max)
|
||||
}
|
||||
|
||||
impl BBox4 {
|
||||
|
@ -26,16 +26,16 @@ impl BBox4 {
|
|||
pub fn new() -> BBox4 {
|
||||
BBox4 {
|
||||
x: (
|
||||
Float4::splat(std::f32::INFINITY),
|
||||
Float4::splat(std::f32::NEG_INFINITY),
|
||||
Vec4::splat(std::f32::INFINITY),
|
||||
Vec4::splat(std::f32::NEG_INFINITY),
|
||||
),
|
||||
y: (
|
||||
Float4::splat(std::f32::INFINITY),
|
||||
Float4::splat(std::f32::NEG_INFINITY),
|
||||
Vec4::splat(std::f32::INFINITY),
|
||||
Vec4::splat(std::f32::NEG_INFINITY),
|
||||
),
|
||||
z: (
|
||||
Float4::splat(std::f32::INFINITY),
|
||||
Float4::splat(std::f32::NEG_INFINITY),
|
||||
Vec4::splat(std::f32::INFINITY),
|
||||
Vec4::splat(std::f32::NEG_INFINITY),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -45,30 +45,30 @@ impl BBox4 {
|
|||
pub fn from_bboxes(b1: BBox, b2: BBox, b3: BBox, b4: BBox) -> BBox4 {
|
||||
BBox4 {
|
||||
x: (
|
||||
Float4::new(b1.min.x(), b2.min.x(), b3.min.x(), b4.min.x()),
|
||||
Float4::new(b1.max.x(), b2.max.x(), b3.max.x(), b4.max.x()),
|
||||
Vec4::new(b1.min.x(), b2.min.x(), b3.min.x(), b4.min.x()),
|
||||
Vec4::new(b1.max.x(), b2.max.x(), b3.max.x(), b4.max.x()),
|
||||
),
|
||||
y: (
|
||||
Float4::new(b1.min.y(), b2.min.y(), b3.min.y(), b4.min.y()),
|
||||
Float4::new(b1.max.y(), b2.max.y(), b3.max.y(), b4.max.y()),
|
||||
Vec4::new(b1.min.y(), b2.min.y(), b3.min.y(), b4.min.y()),
|
||||
Vec4::new(b1.max.y(), b2.max.y(), b3.max.y(), b4.max.y()),
|
||||
),
|
||||
z: (
|
||||
Float4::new(b1.min.z(), b2.min.z(), b3.min.z(), b4.min.z()),
|
||||
Float4::new(b1.max.z(), b2.max.z(), b3.max.z(), b4.max.z()),
|
||||
Vec4::new(b1.min.z(), b2.min.z(), b3.min.z(), b4.min.z()),
|
||||
Vec4::new(b1.max.z(), b2.max.z(), b3.max.z(), b4.max.z()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether the given ray intersects with the bboxes.
|
||||
pub fn intersect_ray(&self, orig: Point, dir_inv: Vector, max_t: f32) -> Bool4 {
|
||||
pub fn intersect_ray(&self, orig: Point, dir_inv: Vector, max_t: f32) -> Vec4Mask {
|
||||
// Get the ray data into SIMD format.
|
||||
let ro_x = orig.co.all_0();
|
||||
let ro_y = orig.co.all_1();
|
||||
let ro_z = orig.co.all_2();
|
||||
let rdi_x = dir_inv.co.all_0();
|
||||
let rdi_y = dir_inv.co.all_1();
|
||||
let rdi_z = dir_inv.co.all_2();
|
||||
let max_t = Float4::splat(max_t);
|
||||
let ro_x = Vec4::splat(orig.co.x());
|
||||
let ro_y = Vec4::splat(orig.co.y());
|
||||
let ro_z = Vec4::splat(orig.co.z());
|
||||
let rdi_x = Vec4::splat(dir_inv.co.x());
|
||||
let rdi_y = Vec4::splat(dir_inv.co.y());
|
||||
let rdi_z = Vec4::splat(dir_inv.co.z());
|
||||
let max_t = Vec4::splat(max_t);
|
||||
|
||||
// Slab tests
|
||||
let t1_x = (self.x.0 - ro_x) * rdi_x;
|
||||
|
@ -79,24 +79,21 @@ impl BBox4 {
|
|||
let t2_z = (self.z.1 - ro_z) * rdi_z;
|
||||
|
||||
// Get the far and near t hits for each axis.
|
||||
let t_far_x = t1_x.v_max(t2_x);
|
||||
let t_far_y = t1_y.v_max(t2_y);
|
||||
let t_far_z = t1_z.v_max(t2_z);
|
||||
let t_near_x = t1_x.v_min(t2_x);
|
||||
let t_near_y = t1_y.v_min(t2_y);
|
||||
let t_near_z = t1_z.v_min(t2_z);
|
||||
let t_far_x = t1_x.max(t2_x);
|
||||
let t_far_y = t1_y.max(t2_y);
|
||||
let t_far_z = t1_z.max(t2_z);
|
||||
let t_near_x = t1_x.min(t2_x);
|
||||
let t_near_y = t1_y.min(t2_y);
|
||||
let t_near_z = t1_z.min(t2_z);
|
||||
|
||||
// Calculate over-all far t hit.
|
||||
let far_t =
|
||||
(t_far_x.v_min(t_far_y.v_min(t_far_z)) * Float4::splat(BBOX_MAXT_ADJUST)).v_min(max_t);
|
||||
let far_t = (t_far_x.min(t_far_y.min(t_far_z)) * Vec4::splat(BBOX_MAXT_ADJUST)).min(max_t);
|
||||
|
||||
// Calculate over-all near t hit.
|
||||
let near_t = t_near_x
|
||||
.v_max(t_near_y)
|
||||
.v_max(t_near_z.v_max(Float4::splat(0.0)));
|
||||
let near_t = t_near_x.max(t_near_y).max(t_near_z.max(Vec4::splat(0.0)));
|
||||
|
||||
// Hit results
|
||||
near_t.lt(far_t)
|
||||
near_t.cmplt(far_t)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,9 +103,9 @@ impl BitOr for BBox4 {
|
|||
|
||||
fn bitor(self, rhs: BBox4) -> BBox4 {
|
||||
BBox4 {
|
||||
x: (self.x.0.v_min(rhs.x.0), self.x.1.v_max(rhs.x.1)),
|
||||
y: (self.y.0.v_min(rhs.y.0), self.y.1.v_max(rhs.y.1)),
|
||||
z: (self.z.0.v_min(rhs.z.0), self.z.1.v_max(rhs.z.1)),
|
||||
x: (self.x.0.min(rhs.x.0), self.x.1.max(rhs.x.1)),
|
||||
y: (self.y.0.min(rhs.y.0), self.y.1.max(rhs.y.1)),
|
||||
z: (self.z.0.min(rhs.z.0), self.z.1.max(rhs.z.1)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
48
src/color.rs
48
src/color.rs
|
@ -4,7 +4,7 @@ pub use color::{
|
|||
rec709_e_to_xyz, rec709_to_xyz, xyz_to_aces_ap0, xyz_to_aces_ap0_e, xyz_to_rec709,
|
||||
xyz_to_rec709_e,
|
||||
};
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
use half::f16;
|
||||
use spectral_upsampling::meng::{spectrum_xyz_to_p_4, EQUAL_ENERGY_REFLECTANCE};
|
||||
use trifloat::signed48;
|
||||
|
@ -31,10 +31,10 @@ fn nth_wavelength(hero_wavelength: f32, n: usize) -> f32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns all wavelengths of a hero wavelength set as a Float4
|
||||
/// Returns all wavelengths of a hero wavelength set as a Vec4
|
||||
#[inline(always)]
|
||||
fn wavelengths(hero_wavelength: f32) -> Float4 {
|
||||
Float4::new(
|
||||
fn wavelengths(hero_wavelength: f32) -> Vec4 {
|
||||
Vec4::new(
|
||||
nth_wavelength(hero_wavelength, 0),
|
||||
nth_wavelength(hero_wavelength, 1),
|
||||
nth_wavelength(hero_wavelength, 2),
|
||||
|
@ -94,11 +94,11 @@ impl Color {
|
|||
} => {
|
||||
SpectralSample::from_parts(
|
||||
// TODO: make this SIMD
|
||||
Float4::new(
|
||||
plancks_law(temperature, wls.get_0()) * factor,
|
||||
plancks_law(temperature, wls.get_1()) * factor,
|
||||
plancks_law(temperature, wls.get_2()) * factor,
|
||||
plancks_law(temperature, wls.get_3()) * factor,
|
||||
Vec4::new(
|
||||
plancks_law(temperature, wls.x()) * factor,
|
||||
plancks_law(temperature, wls.y()) * factor,
|
||||
plancks_law(temperature, wls.z()) * factor,
|
||||
plancks_law(temperature, wls.w()) * factor,
|
||||
),
|
||||
hero_wavelength,
|
||||
)
|
||||
|
@ -109,11 +109,11 @@ impl Color {
|
|||
} => {
|
||||
SpectralSample::from_parts(
|
||||
// TODO: make this SIMD
|
||||
Float4::new(
|
||||
plancks_law_normalized(temperature, wls.get_0()) * factor,
|
||||
plancks_law_normalized(temperature, wls.get_1()) * factor,
|
||||
plancks_law_normalized(temperature, wls.get_2()) * factor,
|
||||
plancks_law_normalized(temperature, wls.get_3()) * factor,
|
||||
Vec4::new(
|
||||
plancks_law_normalized(temperature, wls.x()) * factor,
|
||||
plancks_law_normalized(temperature, wls.y()) * factor,
|
||||
plancks_law_normalized(temperature, wls.z()) * factor,
|
||||
plancks_law_normalized(temperature, wls.w()) * factor,
|
||||
),
|
||||
hero_wavelength,
|
||||
)
|
||||
|
@ -388,7 +388,7 @@ fn plancks_law_normalized(temperature: f32, wavelength: f32) -> f32 {
|
|||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SpectralSample {
|
||||
pub e: Float4,
|
||||
pub e: Vec4,
|
||||
hero_wavelength: f32,
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ impl SpectralSample {
|
|||
pub fn new(wavelength: f32) -> SpectralSample {
|
||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||
SpectralSample {
|
||||
e: Float4::splat(0.0),
|
||||
e: Vec4::splat(0.0),
|
||||
hero_wavelength: wavelength,
|
||||
}
|
||||
}
|
||||
|
@ -405,12 +405,12 @@ impl SpectralSample {
|
|||
pub fn from_value(value: f32, wavelength: f32) -> SpectralSample {
|
||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||
SpectralSample {
|
||||
e: Float4::splat(value),
|
||||
e: Vec4::splat(value),
|
||||
hero_wavelength: wavelength,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_parts(e: Float4, wavelength: f32) -> SpectralSample {
|
||||
pub fn from_parts(e: Vec4, wavelength: f32) -> SpectralSample {
|
||||
debug_assert!(wavelength >= WL_MIN && wavelength <= WL_MAX);
|
||||
SpectralSample {
|
||||
e: e,
|
||||
|
@ -520,10 +520,10 @@ impl XYZ {
|
|||
}
|
||||
|
||||
pub fn from_spectral_sample(ss: &SpectralSample) -> XYZ {
|
||||
let xyz0 = XYZ::from_wavelength(ss.wl_n(0), ss.e.get_0());
|
||||
let xyz1 = XYZ::from_wavelength(ss.wl_n(1), ss.e.get_1());
|
||||
let xyz2 = XYZ::from_wavelength(ss.wl_n(2), ss.e.get_2());
|
||||
let xyz3 = XYZ::from_wavelength(ss.wl_n(3), ss.e.get_3());
|
||||
let xyz0 = XYZ::from_wavelength(ss.wl_n(0), ss.e.x());
|
||||
let xyz1 = XYZ::from_wavelength(ss.wl_n(1), ss.e.y());
|
||||
let xyz2 = XYZ::from_wavelength(ss.wl_n(2), ss.e.z());
|
||||
let xyz3 = XYZ::from_wavelength(ss.wl_n(3), ss.e.w());
|
||||
(xyz0 + xyz1 + xyz2 + xyz3) * 0.75
|
||||
}
|
||||
|
||||
|
@ -601,8 +601,8 @@ impl DivAssign<f32> for XYZ {
|
|||
/// the method in the paper "Physically Meaningful Rendering using Tristimulus
|
||||
/// Colours" by Meng et al.
|
||||
#[inline(always)]
|
||||
fn xyz_to_spectrum_4(xyz: (f32, f32, f32), wavelengths: Float4) -> Float4 {
|
||||
spectrum_xyz_to_p_4(wavelengths, xyz) * Float4::splat(1.0 / EQUAL_ENERGY_REFLECTANCE)
|
||||
fn xyz_to_spectrum_4(xyz: (f32, f32, f32), wavelengths: Vec4) -> Vec4 {
|
||||
spectrum_xyz_to_p_4(wavelengths, xyz) * Vec4::splat(1.0 / EQUAL_ENERGY_REFLECTANCE)
|
||||
// aces_to_spectrum_p4(wavelengths, xyz_to_aces_ap0_e(xyz))
|
||||
}
|
||||
|
||||
|
|
14
src/lerp.rs
14
src/lerp.rs
|
@ -73,23 +73,15 @@ impl<T: Lerp> Lerp for (T, T) {
|
|||
}
|
||||
}
|
||||
|
||||
impl Lerp for float4::Float4 {
|
||||
fn lerp(self, other: float4::Float4, alpha: f32) -> float4::Float4 {
|
||||
impl Lerp for glam::Vec4 {
|
||||
fn lerp(self, other: glam::Vec4, alpha: f32) -> glam::Vec4 {
|
||||
(self * (1.0 - alpha)) + (other * alpha)
|
||||
}
|
||||
}
|
||||
|
||||
impl Lerp for Matrix4x4 {
|
||||
fn lerp(self, other: Matrix4x4, alpha: f32) -> Matrix4x4 {
|
||||
let alpha_minus = 1.0 - alpha;
|
||||
Matrix4x4 {
|
||||
values: [
|
||||
(self[0] * alpha_minus) + (other[0] * alpha),
|
||||
(self[1] * alpha_minus) + (other[1] * alpha),
|
||||
(self[2] * alpha_minus) + (other[2] * alpha),
|
||||
(self[3] * alpha_minus) + (other[3] * alpha),
|
||||
],
|
||||
}
|
||||
(self * (1.0 - alpha)) + (other * alpha)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
src/ray.rs
12
src/ray.rs
|
@ -1,6 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use float4::{Bool4, Float4};
|
||||
use glam::{Vec4, Vec4Mask};
|
||||
|
||||
use crate::math::{Matrix4x4, Point, Vector};
|
||||
|
||||
|
@ -86,7 +86,7 @@ impl RayBatch {
|
|||
pub fn set_from_ray(&mut self, ray: &Ray, is_occlusion: bool, idx: usize) {
|
||||
self.hot[idx].orig_local = ray.orig;
|
||||
self.hot[idx].dir_inv_local = Vector {
|
||||
co: Float4::splat(1.0) / ray.dir.co,
|
||||
co: Vec4::splat(1.0) / ray.dir.co,
|
||||
};
|
||||
self.hot[idx].max_t = ray.max_t;
|
||||
self.hot[idx].time = ray.time;
|
||||
|
@ -122,7 +122,7 @@ impl RayBatch {
|
|||
pub fn update_local(&mut self, idx: usize, xform: &Matrix4x4) {
|
||||
self.hot[idx].orig_local = self.cold[idx].orig * *xform;
|
||||
self.hot[idx].dir_inv_local = Vector {
|
||||
co: Float4::splat(1.0) / (self.cold[idx].dir * *xform).co,
|
||||
co: Vec4::splat(1.0) / (self.cold[idx].dir * *xform).co,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -349,7 +349,7 @@ impl RayStack {
|
|||
/// indicated lanes.
|
||||
pub fn pop_do_next_task_and_push_rays<F>(&mut self, output_lane_count: usize, mut handle_ray: F)
|
||||
where
|
||||
F: FnMut(usize) -> Bool4,
|
||||
F: FnMut(usize) -> Vec4Mask,
|
||||
{
|
||||
// Pop the task and do necessary bookkeeping.
|
||||
let task = self.tasks.pop().unwrap();
|
||||
|
@ -372,9 +372,9 @@ impl RayStack {
|
|||
// Execute task.
|
||||
for i in task_range.0..task_range.1 {
|
||||
let ray_idx = *unsafe { self.lanes[task.lane].idxs.get_unchecked(i) };
|
||||
let push_mask = handle_ray(ray_idx as usize);
|
||||
let push_mask = handle_ray(ray_idx as usize).bitmask();
|
||||
for l in 0..output_lane_count {
|
||||
if push_mask.get_n(l) {
|
||||
if (push_mask & (1 << l)) != 0 {
|
||||
self.lanes[l as usize].idxs.push(ray_idx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
|||
use crossbeam::sync::MsQueue;
|
||||
use scoped_threadpool::Pool;
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
use crate::{
|
||||
accel::ACCEL_NODE_RAY_TESTS,
|
||||
|
@ -374,12 +374,12 @@ pub struct LightPath {
|
|||
wavelength: f32,
|
||||
|
||||
next_bounce_ray: Option<Ray>,
|
||||
next_attenuation_fac: Float4,
|
||||
next_attenuation_fac: Vec4,
|
||||
|
||||
closure_sample_pdf: f32,
|
||||
light_attenuation: Float4,
|
||||
pending_color_addition: Float4,
|
||||
color: Float4,
|
||||
light_attenuation: Vec4,
|
||||
pending_color_addition: Vec4,
|
||||
color: Vec4,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
|
@ -405,12 +405,12 @@ impl LightPath {
|
|||
wavelength: wavelength,
|
||||
|
||||
next_bounce_ray: None,
|
||||
next_attenuation_fac: Float4::splat(1.0),
|
||||
next_attenuation_fac: Vec4::splat(1.0),
|
||||
|
||||
closure_sample_pdf: 1.0,
|
||||
light_attenuation: Float4::splat(1.0),
|
||||
pending_color_addition: Float4::splat(0.0),
|
||||
color: Float4::splat(0.0),
|
||||
light_attenuation: Vec4::splat(1.0),
|
||||
pending_color_addition: Vec4::splat(0.0),
|
||||
color: Vec4::splat(0.0),
|
||||
},
|
||||
scene.camera.generate_ray(
|
||||
image_plane_co.0,
|
||||
|
@ -565,7 +565,7 @@ impl LightPath {
|
|||
|
||||
// If there's any possible contribution, set up for a
|
||||
// light ray.
|
||||
if attenuation.e.h_max() <= 0.0 {
|
||||
if attenuation.e.max_element() <= 0.0 {
|
||||
false
|
||||
} else {
|
||||
// Calculate and store the light that will be contributed
|
||||
|
@ -599,7 +599,7 @@ impl LightPath {
|
|||
};
|
||||
|
||||
// Check if pdf is zero, to avoid NaN's.
|
||||
if (pdf > 0.0) && (filter.e.h_max() > 0.0) {
|
||||
if (pdf > 0.0) && (filter.e.max_element() > 0.0) {
|
||||
// Account for the additional light attenuation from
|
||||
// this bounce
|
||||
self.next_attenuation_fac = filter.e;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::f32::consts::PI as PI_32;
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
use crate::{
|
||||
color::{Color, SpectralSample},
|
||||
|
@ -492,27 +492,27 @@ mod ggx_closure {
|
|||
let spectrum_sample = col.to_spectral_sample(wavelength);
|
||||
let rev_fresnel = 1.0 - fresnel;
|
||||
let c0 = lerp(
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.get_0(), hb),
|
||||
spectrum_sample.e.get_0(),
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.x(), hb),
|
||||
spectrum_sample.e.x(),
|
||||
rev_fresnel,
|
||||
);
|
||||
let c1 = lerp(
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.get_1(), hb),
|
||||
spectrum_sample.e.get_1(),
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.y(), hb),
|
||||
spectrum_sample.e.y(),
|
||||
rev_fresnel,
|
||||
);
|
||||
let c2 = lerp(
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.get_2(), hb),
|
||||
spectrum_sample.e.get_2(),
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.z(), hb),
|
||||
spectrum_sample.e.z(),
|
||||
rev_fresnel,
|
||||
);
|
||||
let c3 = lerp(
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.get_3(), hb),
|
||||
spectrum_sample.e.get_3(),
|
||||
schlick_fresnel_from_fac(spectrum_sample.e.w(), hb),
|
||||
spectrum_sample.e.w(),
|
||||
rev_fresnel,
|
||||
);
|
||||
|
||||
SpectralSample::from_parts(Float4::new(c0, c1, c2, c3), wavelength)
|
||||
SpectralSample::from_parts(Vec4::new(c0, c1, c2, c3), wavelength)
|
||||
};
|
||||
|
||||
// Calculate everything else
|
||||
|
|
|
@ -163,7 +163,7 @@ pub fn surface_point(tri: (Point, Point, Point), bary: (f32, f32, f32)) -> (Poin
|
|||
+ (tri.2.into_vector().abs() * bary.2))
|
||||
* fp_gamma(7))
|
||||
.co
|
||||
.h_max();
|
||||
.max_element();
|
||||
|
||||
(pos, pos_err)
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
[package]
|
||||
name = "float4"
|
||||
version = "0.1.0"
|
||||
authors = ["Nathan Vegdahl <cessen@cessen.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "float4"
|
||||
path = "src/lib.rs"
|
File diff suppressed because it is too large
Load Diff
|
@ -10,5 +10,6 @@ name = "math3d"
|
|||
path = "src/lib.rs"
|
||||
|
||||
# Local crate dependencies
|
||||
[dependencies.float4]
|
||||
path = "../float4"
|
||||
[dependencies]
|
||||
glam = {git="https://github.com/bitshifter/glam-rs.git", rev="0f314f99", default-features=false, features=["approx"]}
|
||||
approx = "0.3"
|
||||
|
|
|
@ -1,29 +1,21 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::ops::{Index, IndexMut, Mul};
|
||||
use std::ops::{Add, Mul};
|
||||
|
||||
use float4::{invert, transpose, Float4};
|
||||
use approx::RelativeEq;
|
||||
use glam::{Mat4, Vec4};
|
||||
|
||||
use super::Point;
|
||||
|
||||
/// A 4x4 matrix, used for transforms
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Matrix4x4 {
|
||||
pub values: [Float4; 4],
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Matrix4x4(pub Mat4);
|
||||
|
||||
impl Matrix4x4 {
|
||||
/// Creates a new identity matrix
|
||||
#[inline]
|
||||
pub fn new() -> Matrix4x4 {
|
||||
Matrix4x4 {
|
||||
values: [
|
||||
Float4::new(1.0, 0.0, 0.0, 0.0),
|
||||
Float4::new(0.0, 1.0, 0.0, 0.0),
|
||||
Float4::new(0.0, 0.0, 1.0, 0.0),
|
||||
Float4::new(0.0, 0.0, 0.0, 1.0),
|
||||
],
|
||||
}
|
||||
Matrix4x4(Mat4::identity())
|
||||
}
|
||||
|
||||
/// Creates a new matrix with the specified values:
|
||||
|
@ -52,108 +44,37 @@ impl Matrix4x4 {
|
|||
o: f32,
|
||||
p: f32,
|
||||
) -> Matrix4x4 {
|
||||
Matrix4x4 {
|
||||
values: [
|
||||
Float4::new(a, b, c, d),
|
||||
Float4::new(e, f, g, h),
|
||||
Float4::new(i, j, k, l),
|
||||
Float4::new(m, n, o, p),
|
||||
],
|
||||
}
|
||||
Matrix4x4(Mat4::new(
|
||||
Vec4::new(a, e, i, m),
|
||||
Vec4::new(b, f, j, n),
|
||||
Vec4::new(c, g, k, o),
|
||||
Vec4::new(d, h, l, p),
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_location(loc: Point) -> Matrix4x4 {
|
||||
Matrix4x4 {
|
||||
values: [
|
||||
Float4::new(1.0, 0.0, 0.0, loc.x()),
|
||||
Float4::new(0.0, 1.0, 0.0, loc.y()),
|
||||
Float4::new(0.0, 0.0, 1.0, loc.z()),
|
||||
Float4::new(0.0, 0.0, 0.0, 1.0),
|
||||
],
|
||||
}
|
||||
Matrix4x4(Mat4::from_translation(loc.co.truncate()))
|
||||
}
|
||||
|
||||
/// Returns whether the matrices are approximately equal to each other.
|
||||
/// Each corresponding element in the matrices cannot have a relative error
|
||||
/// exceeding `epsilon`.
|
||||
/// Each corresponding element in the matrices cannot have a relative
|
||||
/// error exceeding epsilon.
|
||||
#[inline]
|
||||
pub fn aprx_eq(&self, other: Matrix4x4, epsilon: f32) -> bool {
|
||||
let mut result = true;
|
||||
|
||||
for y in 0..4 {
|
||||
for x in 0..4 {
|
||||
// All of this stuff is just an approximate comparison
|
||||
// of floating point numbers. See:
|
||||
// http://floating-point-gui.de/errors/comparison/
|
||||
// It might be worth breaking this out into a separate funcion,
|
||||
// but I'm not entirely sure where to put it.
|
||||
let a = self[y].get_n(x);
|
||||
let b = other[y].get_n(x);
|
||||
let aabs = a.abs();
|
||||
let babs = b.abs();
|
||||
let diff = (a - b).abs();
|
||||
if a == b {
|
||||
} else if (aabs <= std::f32::EPSILON) || (babs <= std::f32::EPSILON) {
|
||||
result = result && (diff < std::f32::EPSILON);
|
||||
} else {
|
||||
let rel = 2.0 * diff / (aabs + babs);
|
||||
println!("{}", rel);
|
||||
result = result && (rel < epsilon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
self.0.relative_eq(&other.0, std::f32::EPSILON, epsilon)
|
||||
}
|
||||
|
||||
/// Returns the transpose of the matrix
|
||||
#[inline]
|
||||
pub fn transposed(&self) -> Matrix4x4 {
|
||||
let mut m = *self;
|
||||
transpose(&mut m.values);
|
||||
m
|
||||
Matrix4x4(self.0.transpose())
|
||||
}
|
||||
|
||||
/// Returns the inverse of the Matrix
|
||||
#[inline]
|
||||
#[allow(clippy::float_cmp)]
|
||||
pub fn inverse(&self) -> Matrix4x4 {
|
||||
let mut m = *self;
|
||||
let det = invert(&mut m.values);
|
||||
debug_assert_ne!(det, 0.0);
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Matrix4x4 {
|
||||
type Output = Float4;
|
||||
|
||||
#[inline(always)]
|
||||
fn index(&self, _index: usize) -> &Float4 {
|
||||
&self.values[_index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for Matrix4x4 {
|
||||
#[inline(always)]
|
||||
fn index_mut(&mut self, _index: usize) -> &mut Float4 {
|
||||
&mut self.values[_index]
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Matrix4x4 {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Matrix4x4) -> bool {
|
||||
let mut result = true;
|
||||
|
||||
for y in 0..4 {
|
||||
for x in 0..4 {
|
||||
result = result && (self[y].get_n(x) == other[y].get_n(x));
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
Matrix4x4(self.0.inverse())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,40 +85,32 @@ impl Default for Matrix4x4 {
|
|||
}
|
||||
|
||||
/// Multiply two matrices together
|
||||
impl Mul<Matrix4x4> for Matrix4x4 {
|
||||
type Output = Matrix4x4;
|
||||
impl Mul for Matrix4x4 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, other: Matrix4x4) -> Matrix4x4 {
|
||||
let m = self.transposed();
|
||||
Matrix4x4 {
|
||||
values: [
|
||||
Float4::new(
|
||||
(m[0] * other[0]).h_sum(),
|
||||
(m[1] * other[0]).h_sum(),
|
||||
(m[2] * other[0]).h_sum(),
|
||||
(m[3] * other[0]).h_sum(),
|
||||
),
|
||||
Float4::new(
|
||||
(m[0] * other[1]).h_sum(),
|
||||
(m[1] * other[1]).h_sum(),
|
||||
(m[2] * other[1]).h_sum(),
|
||||
(m[3] * other[1]).h_sum(),
|
||||
),
|
||||
Float4::new(
|
||||
(m[0] * other[2]).h_sum(),
|
||||
(m[1] * other[2]).h_sum(),
|
||||
(m[2] * other[2]).h_sum(),
|
||||
(m[3] * other[2]).h_sum(),
|
||||
),
|
||||
Float4::new(
|
||||
(m[0] * other[3]).h_sum(),
|
||||
(m[1] * other[3]).h_sum(),
|
||||
(m[2] * other[3]).h_sum(),
|
||||
(m[3] * other[3]).h_sum(),
|
||||
),
|
||||
],
|
||||
fn mul(self, other: Self) -> Self {
|
||||
Self(other.0.mul_mat4(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiply a matrix by a f32
|
||||
impl Mul<f32> for Matrix4x4 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, other: f32) -> Self {
|
||||
Self(self.0 * other)
|
||||
}
|
||||
}
|
||||
|
||||
/// Add two matrices together
|
||||
impl Add for Matrix4x4 {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,22 +131,24 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn aproximate_equality_test() {
|
||||
fn approximate_equality_test() {
|
||||
let a = Matrix4x4::new();
|
||||
let b = Matrix4x4::new_from_values(
|
||||
1.001, 0.0, 0.0, 0.0, 0.0, 1.001, 0.0, 0.0, 0.0, 0.0, 1.001, 0.0, 0.0, 0.0, 0.0, 1.001,
|
||||
1.000001, 0.0, 0.0, 0.0, 0.0, 1.000001, 0.0, 0.0, 0.0, 0.0, 1.000001, 0.0, 0.0, 0.0,
|
||||
0.0, 1.000001,
|
||||
);
|
||||
let c = Matrix4x4::new_from_values(
|
||||
1.003, 0.0, 0.0, 0.0, 0.0, 1.003, 0.0, 0.0, 0.0, 0.0, 1.003, 0.0, 0.0, 0.0, 0.0, 1.003,
|
||||
1.000003, 0.0, 0.0, 0.0, 0.0, 1.000003, 0.0, 0.0, 0.0, 0.0, 1.000003, 0.0, 0.0, 0.0,
|
||||
0.0, 1.000003,
|
||||
);
|
||||
let d = Matrix4x4::new_from_values(
|
||||
-1.001, 0.0, 0.0, 0.0, 0.0, -1.001, 0.0, 0.0, 0.0, 0.0, -1.001, 0.0, 0.0, 0.0, 0.0,
|
||||
-1.001,
|
||||
-1.000001, 0.0, 0.0, 0.0, 0.0, -1.000001, 0.0, 0.0, 0.0, 0.0, -1.000001, 0.0, 0.0, 0.0,
|
||||
0.0, -1.000001,
|
||||
);
|
||||
|
||||
assert!(a.aprx_eq(b, 0.002));
|
||||
assert!(!a.aprx_eq(c, 0.002));
|
||||
assert!(!a.aprx_eq(d, 0.002));
|
||||
assert!(a.aprx_eq(b, 0.000001));
|
||||
assert!(!a.aprx_eq(c, 0.000001));
|
||||
assert!(!a.aprx_eq(d, 0.000001));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -260,7 +175,7 @@ mod tests {
|
|||
let b = a.inverse();
|
||||
let c = Matrix4x4::new();
|
||||
|
||||
assert!((a * b).aprx_eq(c, 0.00001));
|
||||
assert!((dbg!(a * b)).aprx_eq(dbg!(c), 0.0000001));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -5,42 +5,44 @@ use std::{
|
|||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
};
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
use super::{CrossProduct, DotProduct, Matrix4x4, Vector};
|
||||
|
||||
/// A surface normal in 3d homogeneous space.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Normal {
|
||||
pub co: Float4,
|
||||
pub co: Vec4,
|
||||
}
|
||||
|
||||
impl Normal {
|
||||
#[inline(always)]
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Normal {
|
||||
Normal {
|
||||
co: Float4::new(x, y, z, 0.0),
|
||||
co: Vec4::new(x, y, z, 0.0),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn length(&self) -> f32 {
|
||||
(self.co * self.co).h_sum().sqrt()
|
||||
self.co.length()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn length2(&self) -> f32 {
|
||||
(self.co * self.co).h_sum()
|
||||
self.co.length_squared()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn normalized(&self) -> Normal {
|
||||
*self / self.length()
|
||||
Normal {
|
||||
co: self.co.normalize(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn into_vector(self) -> Vector {
|
||||
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
|
||||
Vector { co: self.co }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -55,32 +57,32 @@ impl Normal {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn x(&self) -> f32 {
|
||||
self.co.get_0()
|
||||
self.co.x()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn y(&self) -> f32 {
|
||||
self.co.get_1()
|
||||
self.co.y()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn z(&self) -> f32 {
|
||||
self.co.get_2()
|
||||
self.co.z()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.co.set_0(x);
|
||||
self.co.set_x(x);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.co.set_1(y);
|
||||
self.co.set_y(y);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_z(&mut self, z: f32) {
|
||||
self.co.set_2(z);
|
||||
self.co.set_z(z);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,15 +131,10 @@ impl Mul<Matrix4x4> for Normal {
|
|||
|
||||
#[inline]
|
||||
fn mul(self, other: Matrix4x4) -> Normal {
|
||||
let mat = other.inverse().transposed();
|
||||
Normal {
|
||||
co: Float4::new(
|
||||
(self.co * mat.values[0]).h_sum(),
|
||||
(self.co * mat.values[1]).h_sum(),
|
||||
(self.co * mat.values[2]).h_sum(),
|
||||
0.0,
|
||||
),
|
||||
}
|
||||
let mat = other.0.inverse().transpose();
|
||||
let mut co = mat.mul_vec4(self.co);
|
||||
co.set_w(0.0);
|
||||
Normal { co: co }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +161,7 @@ impl Neg for Normal {
|
|||
impl DotProduct for Normal {
|
||||
#[inline(always)]
|
||||
fn dot(self, other: Normal) -> f32 {
|
||||
(self.co * other.co).h_sum()
|
||||
self.co.dot(other.co)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,12 +169,7 @@ impl CrossProduct for Normal {
|
|||
#[inline]
|
||||
fn cross(self, other: Normal) -> Normal {
|
||||
Normal {
|
||||
co: Float4::new(
|
||||
(self.co.get_1() * other.co.get_2()) - (self.co.get_2() * other.co.get_1()),
|
||||
(self.co.get_2() * other.co.get_0()) - (self.co.get_0() * other.co.get_2()),
|
||||
(self.co.get_0() * other.co.get_1()) - (self.co.get_1() * other.co.get_0()),
|
||||
0.0,
|
||||
),
|
||||
co: self.co.truncate().cross(other.co.truncate()).extend(0.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +178,7 @@ impl CrossProduct for Normal {
|
|||
mod tests {
|
||||
use super::super::{CrossProduct, DotProduct, Matrix4x4};
|
||||
use super::*;
|
||||
use approx::UlpsEq;
|
||||
|
||||
#[test]
|
||||
fn add() {
|
||||
|
@ -220,8 +213,10 @@ mod tests {
|
|||
let m = Matrix4x4::new_from_values(
|
||||
1.0, 2.0, 2.0, 1.5, 3.0, 6.0, 7.0, 8.0, 9.0, 2.0, 11.0, 12.0, 13.0, 7.0, 15.0, 3.0,
|
||||
);
|
||||
let nm = Normal::new(-19.258825, 5.717648, -1.770588);
|
||||
assert!(((n * m) - nm).length2() < 0.00001);
|
||||
let mut nm = n * m;
|
||||
nm.co.set_w(0.0);
|
||||
let nm2 = Normal::new(-19.258825, 5.717648, -1.770588);
|
||||
assert!(nm.co.ulps_eq(&nm2.co, 0.0, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -5,21 +5,21 @@ use std::{
|
|||
ops::{Add, Mul, Sub},
|
||||
};
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
use super::{Matrix4x4, Vector};
|
||||
|
||||
/// A position in 3d homogeneous space.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Point {
|
||||
pub co: Float4,
|
||||
pub co: Vec4,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
#[inline(always)]
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Point {
|
||||
Point {
|
||||
co: Float4::new(x, y, z, 1.0),
|
||||
co: Vec4::new(x, y, z, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ impl Point {
|
|||
#[inline(always)]
|
||||
pub fn norm(&self) -> Point {
|
||||
Point {
|
||||
co: self.co / self.co.get_3(),
|
||||
co: self.co / self.co.w(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ impl Point {
|
|||
let n2 = other.norm();
|
||||
|
||||
Point {
|
||||
co: n1.co.v_min(n2.co),
|
||||
co: n1.co.min(n2.co),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,13 +48,15 @@ impl Point {
|
|||
let n2 = other.norm();
|
||||
|
||||
Point {
|
||||
co: n1.co.v_max(n2.co),
|
||||
co: n1.co.max(n2.co),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn into_vector(self) -> Vector {
|
||||
Vector::new(self.co.get_0(), self.co.get_1(), self.co.get_2())
|
||||
let mut v = Vector { co: self.co };
|
||||
v.co.set_w(0.0);
|
||||
v
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -69,32 +71,32 @@ impl Point {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn x(&self) -> f32 {
|
||||
self.co.get_0()
|
||||
self.co.x()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn y(&self) -> f32 {
|
||||
self.co.get_1()
|
||||
self.co.y()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn z(&self) -> f32 {
|
||||
self.co.get_2()
|
||||
self.co.z()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.co.set_0(x);
|
||||
self.co.set_x(x);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.co.set_1(y);
|
||||
self.co.set_y(y);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_z(&mut self, z: f32) {
|
||||
self.co.set_2(z);
|
||||
self.co.set_z(z);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,12 +146,7 @@ impl Mul<Matrix4x4> for Point {
|
|||
#[inline]
|
||||
fn mul(self, other: Matrix4x4) -> Point {
|
||||
Point {
|
||||
co: Float4::new(
|
||||
(self.co * other.values[0]).h_sum(),
|
||||
(self.co * other.values[1]).h_sum(),
|
||||
(self.co * other.values[2]).h_sum(),
|
||||
(self.co * other.values[3]).h_sum(),
|
||||
),
|
||||
co: other.0.mul_vec4(self.co),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +160,7 @@ mod tests {
|
|||
fn norm() {
|
||||
let mut p1 = Point::new(1.0, 2.0, 3.0);
|
||||
let p2 = Point::new(2.0, 4.0, 6.0);
|
||||
p1.co.set_3(0.5);
|
||||
p1.co.set_w(0.5);
|
||||
|
||||
assert_eq!(p2, p1.norm());
|
||||
}
|
||||
|
@ -203,7 +200,7 @@ mod tests {
|
|||
1.0, 2.0, 2.0, 1.5, 3.0, 6.0, 7.0, 8.0, 9.0, 2.0, 11.0, 12.0, 2.0, 3.0, 1.0, 5.0,
|
||||
);
|
||||
let mut pm = Point::new(15.5, 54.0, 70.0);
|
||||
pm.co.set_3(18.5);
|
||||
pm.co.set_w(18.5);
|
||||
assert_eq!(p * m, pm);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,37 +5,39 @@ use std::{
|
|||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
};
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
use super::{CrossProduct, DotProduct, Matrix4x4, Normal, Point};
|
||||
|
||||
/// A direction vector in 3d homogeneous space.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Vector {
|
||||
pub co: Float4,
|
||||
pub co: Vec4,
|
||||
}
|
||||
|
||||
impl Vector {
|
||||
#[inline(always)]
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Vector {
|
||||
Vector {
|
||||
co: Float4::new(x, y, z, 0.0),
|
||||
co: Vec4::new(x, y, z, 0.0),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn length(&self) -> f32 {
|
||||
(self.co * self.co).h_sum().sqrt()
|
||||
self.co.length()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn length2(&self) -> f32 {
|
||||
(self.co * self.co).h_sum()
|
||||
self.co.length_squared()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn normalized(&self) -> Vector {
|
||||
*self / self.length()
|
||||
Vector {
|
||||
co: self.co.normalize(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -65,32 +67,32 @@ impl Vector {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn x(&self) -> f32 {
|
||||
self.co.get_0()
|
||||
self.co.x()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn y(&self) -> f32 {
|
||||
self.co.get_1()
|
||||
self.co.y()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn z(&self) -> f32 {
|
||||
self.co.get_2()
|
||||
self.co.z()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_x(&mut self, x: f32) {
|
||||
self.co.set_0(x);
|
||||
self.co.set_x(x);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_y(&mut self, y: f32) {
|
||||
self.co.set_1(y);
|
||||
self.co.set_y(y);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_z(&mut self, z: f32) {
|
||||
self.co.set_2(z);
|
||||
self.co.set_z(z);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,12 +142,7 @@ impl Mul<Matrix4x4> for Vector {
|
|||
#[inline]
|
||||
fn mul(self, other: Matrix4x4) -> Vector {
|
||||
Vector {
|
||||
co: Float4::new(
|
||||
(self.co * other.values[0]).h_sum(),
|
||||
(self.co * other.values[1]).h_sum(),
|
||||
(self.co * other.values[2]).h_sum(),
|
||||
(self.co * other.values[3]).h_sum(),
|
||||
),
|
||||
co: other.0.mul_vec4(self.co),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +170,7 @@ impl Neg for Vector {
|
|||
impl DotProduct for Vector {
|
||||
#[inline(always)]
|
||||
fn dot(self, other: Vector) -> f32 {
|
||||
(self.co * other.co).h_sum()
|
||||
self.co.dot(other.co)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,12 +178,7 @@ impl CrossProduct for Vector {
|
|||
#[inline]
|
||||
fn cross(self, other: Vector) -> Vector {
|
||||
Vector {
|
||||
co: Float4::new(
|
||||
(self.co.get_1() * other.co.get_2()) - (self.co.get_2() * other.co.get_1()),
|
||||
(self.co.get_2() * other.co.get_0()) - (self.co.get_0() * other.co.get_2()),
|
||||
(self.co.get_0() * other.co.get_1()) - (self.co.get_1() * other.co.get_0()),
|
||||
0.0,
|
||||
),
|
||||
co: self.co.truncate().cross(other.co.truncate()).extend(0.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +222,7 @@ mod tests {
|
|||
1.0, 2.0, 2.0, 1.5, 3.0, 6.0, 7.0, 8.0, 9.0, 2.0, 11.0, 12.0, 13.0, 7.0, 15.0, 3.0,
|
||||
);
|
||||
let mut vm = Vector::new(14.0, 46.0, 58.0);
|
||||
vm.co.set_3(90.5);
|
||||
vm.co.set_w(90.5);
|
||||
assert_eq!(v * m, vm);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,5 @@ license = "MIT"
|
|||
name = "spectral_upsampling"
|
||||
path = "src/lib.rs"
|
||||
|
||||
# Local crate dependencies
|
||||
[dependencies.float4]
|
||||
path = "../float4"
|
||||
[dependencies]
|
||||
glam = {git="https://github.com/bitshifter/glam-rs.git", rev="0f314f99", default-features=false, features=["approx"]}
|
|
@ -6,7 +6,7 @@
|
|||
/// The provides similar color matching as full Jakob, at the expense of
|
||||
/// somewhat lower quality spectrums, and the inability to precalculate
|
||||
/// the coefficents for even more efficient evaluation later on.
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
/// How many polynomial coefficients?
|
||||
const RGB2SPEC_N_COEFFS: usize = 3;
|
||||
|
@ -15,7 +15,7 @@ const RGB2SPEC_N_COEFFS: usize = 3;
|
|||
include!(concat!(env!("OUT_DIR"), "/jakob_table_inc.rs"));
|
||||
|
||||
#[inline]
|
||||
pub fn rec709_to_spectrum_p4(lambdas: Float4, rgb: (f32, f32, f32)) -> Float4 {
|
||||
pub fn rec709_to_spectrum_p4(lambdas: Vec4, rgb: (f32, f32, f32)) -> Vec4 {
|
||||
small_rgb_to_spectrum_p4(
|
||||
REC709_TABLE,
|
||||
REC709_TABLE_RES,
|
||||
|
@ -26,7 +26,7 @@ pub fn rec709_to_spectrum_p4(lambdas: Float4, rgb: (f32, f32, f32)) -> Float4 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rec2020_to_spectrum_p4(lambdas: Float4, rgb: (f32, f32, f32)) -> Float4 {
|
||||
pub fn rec2020_to_spectrum_p4(lambdas: Vec4, rgb: (f32, f32, f32)) -> Vec4 {
|
||||
small_rgb_to_spectrum_p4(
|
||||
REC2020_TABLE,
|
||||
REC2020_TABLE_RES,
|
||||
|
@ -37,7 +37,7 @@ pub fn rec2020_to_spectrum_p4(lambdas: Float4, rgb: (f32, f32, f32)) -> Float4 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn aces_to_spectrum_p4(lambdas: Float4, rgb: (f32, f32, f32)) -> Float4 {
|
||||
pub fn aces_to_spectrum_p4(lambdas: Vec4, rgb: (f32, f32, f32)) -> Vec4 {
|
||||
small_rgb_to_spectrum_p4(
|
||||
ACES_TABLE,
|
||||
ACES_TABLE_RES,
|
||||
|
@ -55,9 +55,9 @@ fn small_rgb_to_spectrum_p4(
|
|||
table: &[[(f32, f32, f32); 2]],
|
||||
table_res: usize,
|
||||
table_mid_value: f32,
|
||||
lambdas: Float4,
|
||||
lambdas: Vec4,
|
||||
rgb: (f32, f32, f32),
|
||||
) -> Float4 {
|
||||
) -> Vec4 {
|
||||
// Determine largest RGB component, and calculate the other two
|
||||
// components scaled for lookups.
|
||||
let (i, max_val, x, y) = if rgb.0 > rgb.1 && rgb.0 > rgb.2 {
|
||||
|
@ -70,7 +70,7 @@ fn small_rgb_to_spectrum_p4(
|
|||
if max_val == 0.0 {
|
||||
// If max_val is zero, just return zero. This avoids NaN's from
|
||||
// divide by zero. This is also correct, since it's black.
|
||||
return Float4::splat(0.0);
|
||||
return Vec4::splat(0.0);
|
||||
}
|
||||
let x = x * 63.0 / max_val;
|
||||
let y = y * 63.0 / max_val;
|
||||
|
@ -90,20 +90,20 @@ fn small_rgb_to_spectrum_p4(
|
|||
|
||||
// Convert to SIMD format for faster interpolation.
|
||||
let a0 = [
|
||||
Float4::new(a0[0].0, a0[0].1, a0[0].2, 0.0),
|
||||
Float4::new(a0[1].0, a0[1].1, a0[1].2, 0.0),
|
||||
Vec4::new(a0[0].0, a0[0].1, a0[0].2, 0.0),
|
||||
Vec4::new(a0[1].0, a0[1].1, a0[1].2, 0.0),
|
||||
];
|
||||
let a1 = [
|
||||
Float4::new(a1[0].0, a1[0].1, a1[0].2, 0.0),
|
||||
Float4::new(a1[1].0, a1[1].1, a1[1].2, 0.0),
|
||||
Vec4::new(a1[0].0, a1[0].1, a1[0].2, 0.0),
|
||||
Vec4::new(a1[1].0, a1[1].1, a1[1].2, 0.0),
|
||||
];
|
||||
let a2 = [
|
||||
Float4::new(a2[0].0, a2[0].1, a2[0].2, 0.0),
|
||||
Float4::new(a2[1].0, a2[1].1, a2[1].2, 0.0),
|
||||
Vec4::new(a2[0].0, a2[0].1, a2[0].2, 0.0),
|
||||
Vec4::new(a2[1].0, a2[1].1, a2[1].2, 0.0),
|
||||
];
|
||||
let a3 = [
|
||||
Float4::new(a3[0].0, a3[0].1, a3[0].2, 0.0),
|
||||
Float4::new(a3[1].0, a3[1].1, a3[1].2, 0.0),
|
||||
Vec4::new(a3[0].0, a3[0].1, a3[0].2, 0.0),
|
||||
Vec4::new(a3[1].0, a3[1].1, a3[1].2, 0.0),
|
||||
];
|
||||
|
||||
// Do interpolation.
|
||||
|
@ -117,16 +117,14 @@ fn small_rgb_to_spectrum_p4(
|
|||
|
||||
// Evaluate the spectral function and return the result.
|
||||
if max_val <= table_mid_value {
|
||||
rgb2spec_eval_4([c[0].get_0(), c[0].get_1(), c[0].get_2()], lambdas)
|
||||
* (1.0 / table_mid_value)
|
||||
* max_val
|
||||
rgb2spec_eval_4([c[0].x(), c[0].y(), c[0].z()], lambdas) * (1.0 / table_mid_value) * max_val
|
||||
} else if max_val < 1.0 {
|
||||
let n = (max_val - table_mid_value) / (1.0 - table_mid_value);
|
||||
let s0 = rgb2spec_eval_4([c[0].get_0(), c[0].get_1(), c[0].get_2()], lambdas);
|
||||
let s1 = rgb2spec_eval_4([c[1].get_0(), c[1].get_1(), c[1].get_2()], lambdas);
|
||||
let s0 = rgb2spec_eval_4([c[0].x(), c[0].y(), c[0].z()], lambdas);
|
||||
let s1 = rgb2spec_eval_4([c[1].x(), c[1].y(), c[1].z()], lambdas);
|
||||
(s0 * (1.0 - n)) + (s1 * n)
|
||||
} else {
|
||||
rgb2spec_eval_4([c[1].get_0(), c[1].get_1(), c[1].get_2()], lambdas) * max_val
|
||||
rgb2spec_eval_4([c[1].x(), c[1].y(), c[1].z()], lambdas) * max_val
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,18 +132,22 @@ fn small_rgb_to_spectrum_p4(
|
|||
// Coefficient -> eval functions
|
||||
|
||||
#[inline(always)]
|
||||
fn rgb2spec_fma_4(a: Float4, b: Float4, c: Float4) -> Float4 {
|
||||
a.fmadd(b, c)
|
||||
fn rgb2spec_fma_4(a: Vec4, b: Vec4, c: Vec4) -> Vec4 {
|
||||
(a * b) + c
|
||||
}
|
||||
|
||||
fn rgb2spec_eval_4(coeff: [f32; RGB2SPEC_N_COEFFS], lambda: Float4) -> Float4 {
|
||||
let co0 = Float4::splat(coeff[0]);
|
||||
let co1 = Float4::splat(coeff[1]);
|
||||
let co2 = Float4::splat(coeff[2]);
|
||||
fn rgb2spec_eval_4(coeff: [f32; RGB2SPEC_N_COEFFS], lambda: Vec4) -> Vec4 {
|
||||
let co0 = Vec4::splat(coeff[0]);
|
||||
let co1 = Vec4::splat(coeff[1]);
|
||||
let co2 = Vec4::splat(coeff[2]);
|
||||
|
||||
let x = rgb2spec_fma_4(rgb2spec_fma_4(co0, lambda, co1), lambda, co2);
|
||||
|
||||
let y = Float4::splat(1.0) / (rgb2spec_fma_4(x, x, Float4::splat(1.0))).sqrt();
|
||||
let y = {
|
||||
// TODO: replace this with a SIMD sqrt op.
|
||||
let (x, y, z, w) = rgb2spec_fma_4(x, x, Vec4::splat(1.0)).into();
|
||||
Vec4::new(x.sqrt(), y.sqrt(), z.sqrt(), w.sqrt()).reciprocal()
|
||||
};
|
||||
|
||||
rgb2spec_fma_4(Float4::splat(0.5) * x, y, Float4::splat(0.5))
|
||||
rgb2spec_fma_4(Vec4::splat(0.5) * x, y, Vec4::splat(0.5))
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use std::f32;
|
||||
|
||||
use float4::Float4;
|
||||
use glam::Vec4;
|
||||
|
||||
mod meng_spectra_tables;
|
||||
|
||||
|
@ -174,9 +174,9 @@ pub fn spectrum_xyz_to_p(lambda: f32, xyz: (f32, f32, f32)) -> f32 {
|
|||
///
|
||||
/// Works on 4 wavelengths at once via SIMD.
|
||||
#[inline]
|
||||
pub fn spectrum_xyz_to_p_4(lambdas: Float4, xyz: (f32, f32, f32)) -> Float4 {
|
||||
assert!(lambdas.h_min() >= SPECTRUM_SAMPLE_MIN);
|
||||
assert!(lambdas.h_max() <= SPECTRUM_SAMPLE_MAX);
|
||||
pub fn spectrum_xyz_to_p_4(lambdas: Vec4, xyz: (f32, f32, f32)) -> Vec4 {
|
||||
assert!(lambdas.min_element() >= SPECTRUM_SAMPLE_MIN);
|
||||
assert!(lambdas.max_element() <= SPECTRUM_SAMPLE_MAX);
|
||||
|
||||
let inv_norm = xyz.0 + xyz.1 + xyz.2;
|
||||
let norm = {
|
||||
|
@ -184,7 +184,7 @@ pub fn spectrum_xyz_to_p_4(lambdas: Float4, xyz: (f32, f32, f32)) -> Float4 {
|
|||
if norm < f32::MAX {
|
||||
norm
|
||||
} else {
|
||||
return Float4::splat(0.0);
|
||||
return Vec4::splat(0.0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -197,7 +197,7 @@ pub fn spectrum_xyz_to_p_4(lambdas: Float4, xyz: (f32, f32, f32)) -> Float4 {
|
|||
|| uv.1 < 0.0
|
||||
|| uv.1 >= SPECTRUM_GRID_HEIGHT as f32
|
||||
{
|
||||
return Float4::splat(0.0);
|
||||
return Vec4::splat(0.0);
|
||||
}
|
||||
|
||||
let uvi = (uv.0 as i32, uv.1 as i32);
|
||||
|
@ -214,53 +214,48 @@ pub fn spectrum_xyz_to_p_4(lambdas: Float4, xyz: (f32, f32, f32)) -> Float4 {
|
|||
|
||||
// If the cell has no points, nothing we can do, so return 0.0
|
||||
if num == 0 {
|
||||
return Float4::splat(0.0);
|
||||
return Vec4::splat(0.0);
|
||||
}
|
||||
|
||||
// Normalize lambda to spectrum table index range.
|
||||
let sb: Float4 = (lambdas - Float4::splat(SPECTRUM_SAMPLE_MIN))
|
||||
let sb: Vec4 = (lambdas - Vec4::splat(SPECTRUM_SAMPLE_MIN))
|
||||
/ (SPECTRUM_SAMPLE_MAX - SPECTRUM_SAMPLE_MIN)
|
||||
* (SPECTRUM_NUM_SAMPLES as f32 - 1.0);
|
||||
debug_assert!(sb.h_min() >= 0.0);
|
||||
debug_assert!(sb.h_max() <= SPECTRUM_NUM_SAMPLES as f32);
|
||||
debug_assert!(sb.min_element() >= 0.0);
|
||||
debug_assert!(sb.max_element() <= SPECTRUM_NUM_SAMPLES as f32);
|
||||
|
||||
// Get the spectral values for the vertices of the grid cell.
|
||||
// TODO: use integer SIMD intrinsics to make this part faster.
|
||||
let mut p = [Float4::splat(0.0); 6];
|
||||
let sb0: [i32; 4] = [
|
||||
sb.get_0() as i32,
|
||||
sb.get_1() as i32,
|
||||
sb.get_2() as i32,
|
||||
sb.get_3() as i32,
|
||||
];
|
||||
let mut p = [Vec4::splat(0.0); 6];
|
||||
let sb0: [i32; 4] = [sb.x() as i32, sb.y() as i32, sb.z() as i32, sb.w() as i32];
|
||||
assert!(sb0[0].max(sb0[1]).max(sb0[2].max(sb0[3])) < SPECTRUM_NUM_SAMPLES);
|
||||
let sb1: [i32; 4] = [
|
||||
(sb.get_0() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.get_1() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.get_2() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.get_3() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.x() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.y() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.z() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
(sb.w() as i32 + 1).min(SPECTRUM_NUM_SAMPLES - 1),
|
||||
];
|
||||
let sbf = sb - Float4::new(sb0[0] as f32, sb0[1] as f32, sb0[2] as f32, sb0[3] as f32);
|
||||
let sbf = sb - Vec4::new(sb0[0] as f32, sb0[1] as f32, sb0[2] as f32, sb0[3] as f32);
|
||||
for i in 0..(num as usize) {
|
||||
debug_assert!(idx[i] >= 0);
|
||||
let spectrum = &SPECTRUM_DATA_POINTS[idx[i] as usize].spectrum;
|
||||
let p0 = Float4::new(
|
||||
let p0 = Vec4::new(
|
||||
spectrum[sb0[0] as usize],
|
||||
spectrum[sb0[1] as usize],
|
||||
spectrum[sb0[2] as usize],
|
||||
spectrum[sb0[3] as usize],
|
||||
);
|
||||
let p1 = Float4::new(
|
||||
let p1 = Vec4::new(
|
||||
spectrum[sb1[0] as usize],
|
||||
spectrum[sb1[1] as usize],
|
||||
spectrum[sb1[2] as usize],
|
||||
spectrum[sb1[3] as usize],
|
||||
);
|
||||
p[i] = p0 * (Float4::splat(1.0) - sbf) + p1 * sbf;
|
||||
p[i] = p0 * (Vec4::splat(1.0) - sbf) + p1 * sbf;
|
||||
}
|
||||
|
||||
// Linearly interpolate the spectral power of the cell vertices.
|
||||
let mut interpolated_p = Float4::splat(0.0);
|
||||
let mut interpolated_p = Vec4::splat(0.0);
|
||||
if inside {
|
||||
// Fast path for normal inner quads:
|
||||
let uv2 = (uv.0 - uvi.0 as f32, uv.1 - uvi.1 as f32);
|
||||
|
|
Loading…
Reference in New Issue
Block a user