1use std::ops::MulAssign;
2
3use nalgebra as na;
5pub struct AcesFitted {
8 rgb_to_rrt: na::Matrix3<f32>,
9 odt_to_rgb: na::Matrix3<f32>,
10}
11impl AcesFitted {
12 #[allow(clippy::new_without_default)]
13 pub fn new() -> Self {
14 let rgb_to_rrt = na::Matrix3::<f32>::from_columns(&[
16 na::Vector3::new(0.59719, 0.35458, 0.04823),
17 na::Vector3::new(0.07600, 0.90834, 0.01566),
18 na::Vector3::new(0.02840, 0.13383, 0.83777),
19 ]);
20 let odt_to_rgb = na::Matrix3::<f32>::from_columns(&[
21 na::Vector3::new(1.60475, -0.53108, -0.07367),
22 na::Vector3::new(-0.10208, 1.10813, -0.00605),
23 na::Vector3::new(-0.00327, -0.07276, 1.07602),
24 ]);
25 Self { rgb_to_rrt, odt_to_rgb }
26 }
27 pub fn tonemap(&self, color: &na::Vector3<f32>) -> na::Vector3<f32> {
28 let mut fitted_color = color.transpose();
29 fitted_color.mul_assign(&self.rgb_to_rrt);
30
31 fitted_color = Self::rrt_and_odt_fit(&fitted_color);
33
34 fitted_color.mul_assign(&self.odt_to_rgb);
35
36 fitted_color.x = fitted_color.x.clamp(0.0, 1.0);
38 fitted_color.y = fitted_color.y.clamp(0.0, 1.0);
39 fitted_color.z = fitted_color.z.clamp(0.0, 1.0);
40
41 fitted_color.transpose()
42 }
43 fn rrt_and_odt_fit(
44 v: &na::Matrix<f32, na::Const<1>, na::Const<3>, na::ArrayStorage<f32, 1, 3>>,
45 ) -> na::Matrix<f32, na::Const<1>, na::Const<3>, na::ArrayStorage<f32, 1, 3>> {
46 let v1 = v.add_scalar(0.024_578_6);
47 let v2 = v.component_mul(&v1);
48 let a = v2.add_scalar(-0.000_090_537);
49
50 let v1 = 0.983_729 * v;
51 let v2 = v1.add_scalar(0.432_951);
52 let v3 = v.component_mul(&v2);
53 let b = v3.add_scalar(0.238_081);
54 a.component_div(&b)
55 }
56}