psychopath/src/fp_utils.rs

59 lines
1.3 KiB
Rust

//! Utilities for handling floating point precision issues
//!
//! This is based on the work in section 3.9 of "Physically Based Rendering:
//! From Theory to Implementation" 3rd edition by Pharr et al.
use crate::math::{dot, Normal, Point, Vector};
pub use rmath::utils::{decrement_ulp, increment_ulp};
#[inline(always)]
pub fn fp_gamma(n: u32) -> f32 {
use std::f32::EPSILON;
let e = EPSILON * 0.5;
(e * n as f32) / (1.0 - (e * n as f32))
}
pub fn robust_ray_origin(pos: Point, pos_err: f32, nor: Normal, ray_dir: Vector) -> Point {
// Get surface normal pointing in the same
// direction as ray_dir.
let nor = {
let nor = nor.into_vector();
if dot(nor, ray_dir) >= 0.0 {
nor
} else {
-nor
}
};
// Calculate offset point
let d = dot(nor.abs(), Vector::new(pos_err, pos_err, pos_err));
let offset = nor * d;
let p = pos + offset;
// Calculate ulp offsets
let x = if nor.x() >= 0.0 {
increment_ulp(p.x())
} else {
decrement_ulp(p.x())
};
let y = if nor.y() >= 0.0 {
increment_ulp(p.y())
} else {
decrement_ulp(p.y())
};
let z = if nor.z() >= 0.0 {
increment_ulp(p.z())
} else {
decrement_ulp(p.z())
};
Point::new(x, y, z)
}
// #[cfg(test)]
// mod tests {
// use super::*;
// }