1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef API_RENDER_SHADERS_COMMON_TONEMAP_COMMON_H
17 #define API_RENDER_SHADERS_COMMON_TONEMAP_COMMON_H
18
19 #include "render_post_process_common.h"
20
21 /*
22 Aces tonemapping.
23 https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
24 */
TonemapAces(vec3 x)25 vec3 TonemapAces(vec3 x)
26 {
27 const float a = 2.51f;
28 const float b = 0.03f;
29 const float c = 2.43f;
30 const float d = 0.59f;
31 const float e = 0.14f;
32 return (x * (a * x + b)) / (x * (c * x + d) + e);
33 }
34
35 /*
36 Aces film rec 2020 tonemapping.
37 https://knarkowicz.wordpress.com/2016/08/31/hdr-display-first-steps/
38 */
TonemapAcesFilmRec2020(vec3 x)39 vec3 TonemapAcesFilmRec2020(vec3 x)
40 {
41 float a = 15.8f;
42 float b = 2.12f;
43 float c = 1.2f;
44 float d = 5.92f;
45 float e = 1.9f;
46 return (x * (a * x + b)) / (x * (c * x + d) + e);
47 }
48
49 /*
50 Filmic tonemapping.
51 // http://filmicgames.com/archives/75
52 */
TonemapFilmic(float x)53 float TonemapFilmic(float x)
54 {
55 const float a = 0.15f;
56 const float b = 0.50f;
57 const float c = 0.10f;
58 const float d = 0.20f;
59 const float e = 0.02f;
60 const float f = 0.30f;
61 return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
62 }
TonemapFilmic(vec3 x)63 vec3 TonemapFilmic(vec3 x)
64 {
65 const float a = 0.15f;
66 const float b = 0.50f;
67 const float c = 0.10f;
68 const float d = 0.20f;
69 const float e = 0.02f;
70 const float f = 0.30f;
71 const float w = 11.2f;
72 const vec3 curr = ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
73 const float whiteScale = 1.0 / TonemapFilmic(w);
74 return curr * vec3(whiteScale);
75 }
76
77 /*
78 PBR Neutral tonemapping.
79 https://github.com/KhronosGroup/ToneMapping
80 Input color is non-negative and resides in the Linear Rec. 709 color space.
81 Output color is also Linear Rec. 709, but in the [0, 1] range.
82 */
TonemapPbrNeutral(vec3 color)83 vec3 TonemapPbrNeutral(vec3 color)
84 {
85 const float startCompression = 0.8 - 0.04;
86 const float desaturation = 0.15;
87
88 float x = min(color.r, min(color.g, color.b));
89 float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
90 color -= offset;
91
92 float peak = max(color.r, max(color.g, color.b));
93 if (peak < startCompression)
94 return color;
95
96 const float d = 1. - startCompression;
97 float newPeak = 1. - d * d / (peak + d - startCompression);
98 color *= newPeak / peak;
99
100 float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
101 return mix(color, vec3(newPeak), g);
102 }
103
104 #endif // API_RENDER_SHADERS_COMMON_TONEMAP_COMMON_H
105