1 | // Copyright (C) 2008-2012 NVIDIA Corporation. |
2 | // Copyright (C) 2022 The Qt Company Ltd. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
4 | |
5 | #ifndef QSSGCPUTONEMAPPER_P_H |
6 | #define QSSGCPUTONEMAPPER_P_H |
7 | |
8 | // |
9 | // W A R N I N G |
10 | // ------------- |
11 | // |
12 | // This file is not part of the Qt API. It exists purely as an |
13 | // implementation detail. This header file may change from version to |
14 | // version without notice, or even be removed. |
15 | // |
16 | // We mean it. |
17 | // |
18 | |
19 | #include <QtGui/qvector3d.h> |
20 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | namespace QSSGTonemapper { |
24 | |
25 | inline QVector3D vsqrt(const QVector3D &a) |
26 | { |
27 | return QVector3D(std::sqrt(x: a.x()), std::sqrt(x: a.y()), std::sqrt(x: a.z())); |
28 | } |
29 | |
30 | inline QVector3D vmax(const QVector3D &a, const QVector3D &b) |
31 | { |
32 | return QVector3D(std::max(a: a.x(), b: b.x()), std::max(a: a.y(), b: b.y()), std::max(a: a.z(), b: b.z())); |
33 | } |
34 | |
35 | inline QVector3D vclamp(const QVector3D &a, float b, float c) |
36 | { |
37 | return QVector3D(qBound(min: b, val: a.x(), max: c), qBound(min: b, val: a.y(), max: c), qBound(min: b, val: a.z(), max: c)); |
38 | } |
39 | |
40 | inline QVector3D vadd(const QVector3D &a, float b) |
41 | { |
42 | return QVector3D(a.x() + b, a.y() + b, a.z() + b); |
43 | } |
44 | |
45 | template<typename mType> |
46 | inline QVector3D mad(mType m, const QVector3D &a, float b) |
47 | { |
48 | return vadd(m * a, b); |
49 | } |
50 | |
51 | // all the implementation here is expected to match tonemapper.glsllib |
52 | |
53 | inline QVector3D tonemapLinearToSrgb(const QVector3D &c) |
54 | { |
55 | const QVector3D S1 = vsqrt(a: c); |
56 | const QVector3D S2 = vsqrt(a: S1); |
57 | const QVector3D S3 = vsqrt(a: S2); |
58 | return 0.58512238f * S1 + 0.78314035f * S2 - 0.36826273f * S3; |
59 | } |
60 | |
61 | inline QVector3D tonemapHejlDawson(const QVector3D &c) |
62 | { |
63 | const QVector3D cc = vmax(a: QVector3D(0.0f, 0.0f, 0.0f), b: vadd(a: c, b: -0.004f)); |
64 | return (cc * mad(m: 6.2f, a: cc, b: 0.5f)) / vadd(a: cc * mad(m: 6.2f, a: cc, b: 1.7f), b: 0.06f); |
65 | } |
66 | |
67 | inline QVector3D tonemapAces(const QVector3D &c) |
68 | { |
69 | const float A = 2.51f; |
70 | const float B = 0.03f; |
71 | const float C = 2.43f; |
72 | const float D = 0.59f; |
73 | const float E = 0.14f; |
74 | return tonemapLinearToSrgb(c: vclamp(a: (c * mad(m: A, a: c, b: B)) / vadd(a: c * mad(m: C, a: c, b: D), b: E), b: 0.0f, c: 1.0f)); |
75 | } |
76 | |
77 | inline QVector3D tonemapFilmicSub(const QVector3D &c) |
78 | { |
79 | const float A = 0.15f; |
80 | const float B = 0.50f; |
81 | const float C = 0.10f; |
82 | const float D = 0.20f; |
83 | const float E = 0.02f; |
84 | const float F = 0.30f; |
85 | return vadd(a: vadd(a: c * mad(m: A, a: c, b: C * B), b: D * E) / vadd(a: c * mad(m: A, a: c, b: B), b: D * F), b: -E / F); |
86 | } |
87 | |
88 | inline QVector3D tonemapFilmic(const QVector3D &c) |
89 | { |
90 | static const QVector3D whiteScale = QVector3D(1.0f, 1.0f, 1.0f) / tonemapFilmicSub(c: QVector3D(11.2f, 11.2f, 11.2f)); |
91 | return tonemapLinearToSrgb(c: tonemapFilmicSub(c: c * 2.0f) * whiteScale); |
92 | } |
93 | |
94 | } // namespace QSSGTonemapper |
95 | |
96 | QT_END_NAMESPACE |
97 | |
98 | #endif |
99 | |