Merge branch 'xacrimon/sgrbf' into 'master'

Faster sgrb saturation

See merge request veloren/veloren!508
This commit is contained in:
Joshua Barretto 2019-09-24 10:27:46 +00:00
commit d33671f9c1

View File

@ -2,6 +2,39 @@ pub const GIT_HASH: &str = include_str!(concat!(env!("OUT_DIR"), "/githash"));
use vek::{Mat3, Rgb, Rgba, Vec3};
/// This is a fast approximation of powf. This should only be used when minor accuracy loss is acceptable.
#[inline(always)]
#[allow(unsafe_code)]
fn approx_powf(b: f32, e: f32) -> f32 {
unsafe {
let b = b as f64;
let e = e as f64;
union Swagger {
f: f64,
a: [i32; 2],
}
let mut b = Swagger { f: b };
b.a[1] = (e * (b.a[1] as f64 - 1072632447.0) + 1072632447.0) as i32;
b.a[0] = 0;
b.f as f32
}
}
#[cfg(test)]
mod approx_powf_tests {
fn close_ei(a: f32, b: f32) -> bool {
(a - b < 1.0 && a - b > 0.0) || (b - a < 1.0 && b - a > 0.0)
}
#[test]
fn accuracy_1() {
let test_values: Vec<f32> = vec![3.0, 2.5, 1.5, 2.2];
test_values.windows(2).for_each(|a| {
assert!(close_ei(a[0].powf(a[1]), super::approx_powf(a[0], a[1])));
});
}
}
#[inline(always)]
pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
#[inline(always)]
@ -9,7 +42,7 @@ pub fn srgb_to_linear(col: Rgb<f32>) -> Rgb<f32> {
if x <= 0.04045 {
x / 12.92
} else {
((x + 0.055) / 1.055).powf(2.4)
approx_powf((x + 0.055) / 1.055, 2.4)
}
}
col.map(to_linear)
@ -21,7 +54,7 @@ pub fn linear_to_srgb(col: Rgb<f32>) -> Rgb<f32> {
if x <= 0.0031308 {
x * 12.92
} else {
x.powf(1.0 / 2.4) * 1.055 - 0.055
approx_powf(x, 1.0 / 2.4) * 1.055 - 0.055
}
}
col.map(to_srgb)
@ -118,6 +151,7 @@ pub fn xyy_to_rgb(xyy: Vec3<f32>) -> Rgb<f32> {
)
}
// TO-DO: speed this up
#[inline(always)]
pub fn saturate_srgb(col: Rgb<f32>, value: f32) -> Rgb<f32> {
let mut hsv = rgb_to_hsv(srgb_to_linear(col));