| 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 | |