three_d/renderer/viewer/tone_mapping.rs
1use crate::core::*;
2
3///
4/// Tone mapping is the process of mapping HDR color values computed with physical based rendering in the range `[0,∞)`
5/// into LDR values that can be displayed on the screen in the range `[0,1]`.
6///
7#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
8pub enum ToneMapping {
9 /// No tone mapping. Use this if you are rendering into an intermediate render target, ie. this is not the final render pass that renders into the screen.
10 None = 0,
11 /// Photographic Tone Reproduction for Digital Images. `<http://www.cmap.polytechnique.fr/~peyre/cours/x2005signal/hdr_photographic.pdf>`
12 Reinhard = 1,
13 /// ACES Filmic Tone Mapping Curve. `<https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/>`
14 #[default]
15 Aces = 2,
16 /// John Hables presentation "Uncharted 2 HDR Lighting", Page 142 to 143. `<http://www.gdcvault.com/play/1012459/Uncharted_2__HDR_Lighting>`
17 Filmic = 3,
18}
19
20impl ToneMapping {
21 ///
22 /// Returns the fragment shader source for applying the specified tone mapping in a shader.
23 ///
24 pub fn fragment_shader_source() -> &'static str {
25 "
26 uniform uint toneMappingType;
27
28 vec3 tone_mapping(vec3 color) {
29 if (toneMappingType == 1u) {
30 color = color / (color + vec3(1.0));
31 color = clamp(color, 0.0, 1.0);
32 } else if(toneMappingType == 2u) {
33 color = color*(2.51*color + .03) / (color*(2.43*color + .59) + .14);
34 color = clamp(color, 0.0, 1.0);
35 } else if(toneMappingType == 3u) {
36 const float A = 0.15;
37 const float B = 0.50;
38 const float C = 0.10;
39 const float D = 0.20;
40 const float E = 0.02;
41 const float F = 0.30;
42 const float W = 11.2;
43
44 vec4 x = vec4(color, W);
45 x = ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
46 color = x.xyz / x.w;
47 color = clamp(color, 0.0, 1.0);
48 }
49 return color;
50 }
51 "
52 }
53
54 ///
55 /// Sends the uniform data needed to apply this tone mapping to the fragment shader.
56 ///
57 pub fn use_uniforms(&self, program: &Program) {
58 program.use_uniform("toneMappingType", *self as u32);
59 }
60}