aboutsummaryrefslogtreecommitdiffstats
path: root/src/runtimerender/res/effectlib/tonemapping.glsllib
blob: 87fe64935bf4cd68a3178fab757285f1bf7360c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#ifndef TONEMAPPPING_GLSLIB
#define TONEMAPPPING_GLSLIB 1

// This file is also included from the static shader skybox.frag, therefore pay
// attention that it should be suitable both as a generator-included and as a
// static-shader-included snippet. It may also be included from post-processing
// effect fragment shaders.

// Any changes to the calculations must be reflected in qssgcputonemapper_p.h.

#ifndef QSSG_ENABLE_LINEAR_TONEMAPPING
#define QSSG_ENABLE_LINEAR_TONEMAPPING 0
#endif
#ifndef QSSG_ENABLE_ACES_TONEMAPPING
#define QSSG_ENABLE_ACES_TONEMAPPING 0
#endif
#ifndef QSSG_ENABLE_HEJLDAWSON_TONEMAPPING
#define QSSG_ENABLE_HEJLDAWSON_TONEMAPPING 0
#endif
#ifndef QSSG_ENABLE_FILMIC_TONEMAPPING
#define QSSG_ENABLE_FILMIC_TONEMAPPING 0
#endif
#ifndef QSSG_FORCE_IBL_EXPOSURE
#define QSSG_FORCE_IBL_EXPOSURE 0
#endif

// The following methods are described in this article:
// http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html

// The following 4 methods are the most accurate approximations
vec3 qt_linearTosRGB(vec3 color)
{
    vec3 S1 = sqrt(color);
    vec3 S2 = sqrt(S1);
    vec3 S3 = sqrt(S2);
    return 0.585122381 * S1 + 0.783140355 * S2 - 0.368262736 * S3;
}

vec3 qt_sRGBToLinear(vec3 srgbIn)
{
    return srgbIn * (srgbIn * (srgbIn * 0.305306011 + 0.682171111) + 0.012522878);
}

vec4 qt_linearTosRGB(vec4 color)
{
    return vec4(qt_linearTosRGB(color.rgb), color.a);
}

vec4 qt_sRGBToLinear(vec4 srgbIn)
{
    return vec4(qt_sRGBToLinear(srgbIn.rgb), srgbIn.a);
}

const float GAMMA = 2.2;
const float INV_GAMMA = 1.0 / GAMMA;

// The following 4 methods are the fastest, but less accurate

vec3 qt_linearTosRGBFast(vec3 color)
{
    return pow(color, vec3(INV_GAMMA));
}

vec3 qt_sRGBToLinearFast(vec3 srgbIn)
{
    return vec3(pow(srgbIn.xyz, vec3(GAMMA)));
}

vec4 qt_linearTosRGBFast(vec4 color)
{
    return vec4(pow(color.rgb, vec3(INV_GAMMA)), color.a);
}

vec4 qt_sRGBToLinearFast(vec4 srgbIn)
{
    return vec4(pow(srgbIn.rgb, vec3(GAMMA)), srgbIn.a);
}

#if QSSG_ENABLE_ACES_TONEMAPPING
vec3 qt_toneMapACES(vec3 color)
{
    const float A = 2.51;
    const float B = 0.03;
    const float C = 2.43;
    const float D = 0.59;
    const float E = 0.14;
    return qt_linearTosRGB(clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0));
}
#endif

#if QSSG_ENABLE_HEJLDAWSON_TONEMAPPING
vec3 qt_tonemapHejlDawson(vec3 color)
{
    color = max(vec3(0.0), color - vec3(0.004));
    return (color * (6.2 * color + 0.5)) / (color * (6.2 * color + 1.7) + 0.06);
}
#endif

#if QSSG_ENABLE_FILMIC_TONEMAPPING
vec3 qt_toneMapFilmicSub(vec3 color)
{
    const float A = 0.15;
    const float B = 0.50;
    const float C = 0.10;
    const float D = 0.20;
    const float E = 0.02;
    const float F = 0.30;
    return ((color * ( A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
}

vec3 qt_toneMapFilmic(vec3 color)
{
    color = qt_toneMapFilmicSub(color * 2.0);
    vec3 whiteScale = 1.0 / qt_toneMapFilmicSub(vec3(11.2, 11.2, 11.2));
    return qt_linearTosRGB(color * whiteScale);
}
#endif

// Call this method to perform tonemapping with the correct tonemapper
vec3 qt_tonemap(vec3 color)
{
    // ACES
#if QSSG_ENABLE_ACES_TONEMAPPING
    return qt_toneMapACES(color);
#endif
    // Hejl-Dawson
#if QSSG_ENABLE_HEJLDAWSON_TONEMAPPING
    return qt_tonemapHejlDawson(color);
#endif

    // Filmic
#if QSSG_ENABLE_FILMIC_TONEMAPPING
    return qt_toneMapFilmic(color);
#endif

    // Linear
#if QSSG_ENABLE_LINEAR_TONEMAPPING
    return qt_linearTosRGB(color);
#endif

    return color;
}

vec4 qt_tonemap(vec4 color)
{
    return vec4(qt_tonemap(color.rgb), color.a);
}

vec3 qt_exposure(vec3 color, float exposure)
{
#if QSSG_ENABLE_ACES_TONEMAPPING || QSSG_ENABLE_HEJLDAWSON_TONEMAPPING || QSSG_ENABLE_FILMIC_TONEMAPPING || QSSG_ENABLE_LINEAR_TONEMAPPING || QSSG_FORCE_IBL_EXPOSURE
    return vec3(vec3(1.0) - exp(-color * exposure));
#else
    return color;
#endif
}

#endif // TONEMAPPPING_GLSLIB