From 64c2ab7048d3c8e7b52d2f77192f4cb3971f1e34 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Wed, 14 Jul 2021 22:18:07 -0700 Subject: [PATCH] Generalize luminance scaling in color grading (#4321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Generalize luminance scaling in color grading Previously the luminance scaling step was tied to a specific tone mapping operator, called "EVILS" in the API. This was however somewhat misleading as EVILS really is a color handling system that's independent of what we call tone mapping. This change splits the luminance scaling step from the tone mapping step, allowing the use of luminance scaling (the LICH part of EVILS) with any tone mapping operator. As a result, the operator known as EVILS is currently mapped to the linear operator and renamed to "RESERVED" until it is replaced by a proper — configurable — operator. * Update release notes * Fix web build --- RELEASE_NOTES.md | 4 + .../src/main/cpp/ColorGrading.cpp | 7 ++ .../google/android/filament/ColorGrading.java | 26 +++++- filament/include/filament/ColorGrading.h | 20 ++++- filament/src/ColorGrading.cpp | 85 ++++++++++++++++--- filament/src/ToneMapping.cpp | 55 +++--------- filament/src/ToneMapping.h | 2 - libs/viewer/include/viewer/Settings.h | 1 + libs/viewer/src/Settings.cpp | 9 +- libs/viewer/src/SimpleViewer.cpp | 3 +- libs/viewer/tests/test_settings.cpp | 1 + samples/material_sandbox.cpp | 4 +- samples/material_sandbox.h | 2 + web/filament-js/jsenums.cpp | 2 +- 14 files changed, 156 insertions(+), 65 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b3fac3b18a..c430c39172 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,6 +5,10 @@ A new header is inserted each time a *tag* is created. ## v1.11.1 (currently main branch) +- engine: Luminance scaling can now be used with any tone mapping operator. It was previously tied + to the "EVILS" tone mapping operator. +- engine: Removed the "EVILS" tone mapping operator [⚠️ **API Change**]. + ## v1.11.0 - engine: Added support for transparent shadows. Add `transparentShadow : true` in the material file. diff --git a/android/filament-android/src/main/cpp/ColorGrading.cpp b/android/filament-android/src/main/cpp/ColorGrading.cpp index 814012cafc..725e88dd4f 100644 --- a/android/filament-android/src/main/cpp/ColorGrading.cpp +++ b/android/filament-android/src/main/cpp/ColorGrading.cpp @@ -60,6 +60,13 @@ Java_com_google_android_filament_ColorGrading_nBuilderToneMapping(JNIEnv*, jclas builder->toneMapping(toneMapping); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_ColorGrading_nBuilderLuminanceScaling(JNIEnv*, jclass, + jlong nativeBuilder, jboolean luminanceScaling) { + ColorGrading::Builder* builder = (ColorGrading::Builder*) nativeBuilder; + builder->luminanceScaling(luminanceScaling); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_ColorGrading_nBuilderExposure(JNIEnv*, jclass, jlong nativeBuilder, jfloat exposure) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java b/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java index da54f06f99..2118257ba6 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java +++ b/android/filament-android/src/main/java/com/google/android/filament/ColorGrading.java @@ -64,6 +64,7 @@ import static com.google.android.filament.Asserts.assertFloat4In; *
  • Saturation
  • *
  • Curves
  • *
  • Tone mapping
  • + *
  • Luminance scaling
  • * * *

    Defaults

    @@ -81,6 +82,7 @@ import static com.google.android.filament.Asserts.assertFloat4In; *
  • Saturation: 1.0
  • *
  • Curves: gamma {1,1,1}, midPoint {1,1,1}, and scale {1,1,1}
  • *
  • Tone mapping: {@link ToneMapping#ACES_LEGACY}
  • + *
  • Luminance scaling: false
  • * * * @see View @@ -111,8 +113,8 @@ public class ColorGrading { ACES, /** Filmic tone mapping, modelled after ACES but applied in sRGB space. */ FILMIC, - /** Exposure value invariant luminance scaling tone mapping, offers the best behaviors in high intensity areas. */ - EVILS, + /** Reserved for future use. */ + RESERVED, /** Reinhard luma-based tone mapping. */ REINHARD, /** Tone mapping used to validate/debug scene exposure. */ @@ -173,6 +175,25 @@ public class ColorGrading { return this; } + /** + * Enables or disables the luminance scaling component (LICH) from the exposure value + * invariant luminance system (EVILS). When this setting is enabled, pixels with high + * chromatic values will roll-off to white to offer a more natural rendering. This step + * also helps avoid undesirable hue skews caused by out of gamut colors clipped + * to the destination color gamut. + * + * When luminance scaling is enabled, tone mapping is performed on the luminance of each + * pixel instead of per-channel. + * + * @param luminanceScaling Enables or disables EVILS post-tone mapping + * + * @return This Builder, for chaining calls + */ + public Builder luminanceScaling(boolean luminanceScaling) { + nBuilderLuminanceScaling(mNativeBuilder, luminanceScaling); + return this; + } + /** * Adjusts the exposure of this image. The exposure is specified in stops: * each stop brightens (positive values) or darkens (negative values) the image by @@ -482,6 +503,7 @@ public class ColorGrading { private static native void nBuilderQuality(long nativeBuilder, int quality); private static native void nBuilderToneMapping(long nativeBuilder, int toneMapper); + private static native void nBuilderLuminanceScaling(long nativeBuilder, boolean luminanceScaling); private static native void nBuilderExposure(long nativeBuilder, float exposure); private static native void nBuilderWhiteBalance(long nativeBuilder, float temperature, float tint); private static native void nBuilderChannelMixer(long nativeBuilder, float[] outRed, float[] outGreen, float[] outBlue); diff --git a/filament/include/filament/ColorGrading.h b/filament/include/filament/ColorGrading.h index 4b4d88e42b..cf336c16ad 100644 --- a/filament/include/filament/ColorGrading.h +++ b/filament/include/filament/ColorGrading.h @@ -74,6 +74,7 @@ class FColorGrading; * - Saturation * - Curves * - Tone mapping + * - Luminance scaling * * Defaults * ======== @@ -90,6 +91,7 @@ class FColorGrading; * - Saturation: 1.0 * - Curves: gamma {1,1,1}, midPoint {1,1,1}, and scale {1,1,1} * - Tone mapping: ACES_LEGACY + * - Luminance scaling: false * * @see View */ @@ -111,7 +113,7 @@ public: ACES_LEGACY = 1, //!< ACES tone mapping, with a brightness modifier to match Filament's legacy tone mapper ACES = 2, //!< ACES tone mapping FILMIC = 3, //!< Filmic tone mapping, modelled after ACES but applied in sRGB space - EVILS = 4, //!< Exposure value invariant luminance scaling tone mapping, offers the best behaviors in high intensity areas + RESERVED = 4, //!< Currently unused REINHARD = 5, //!< Reinhard luma-based tone mapping DISPLAY_RANGE = 6, //!< Tone mapping used to validate/debug scene exposure }; @@ -154,6 +156,22 @@ public: */ Builder& toneMapping(ToneMapping toneMapping) noexcept; + /** + * Enables or disables the luminance scaling component (LICH) from the exposure value + * invariant luminance system (EVILS). When this setting is enabled, pixels with high + * chromatic values will roll-off to white to offer a more natural rendering. This step + * also helps avoid undesirable hue skews caused by out of gamut colors clipped + * to the destination color gamut. + * + * When luminance scaling is enabled, tone mapping is performed on the luminance of each + * pixel instead of per-channel. + * + * @param luminanceScaling Enables or disables EVILS post-tone mapping + * + * @return This Builder, for chaining calls + */ + Builder& luminanceScaling(bool luminanceScaling) noexcept; + /** * Adjusts the exposure of this image. The exposure is specified in stops: * each stop brightens (positive values) or darkens (negative values) the image by diff --git a/filament/src/ColorGrading.cpp b/filament/src/ColorGrading.cpp index d2dd509005..b6dcb9b3a6 100644 --- a/filament/src/ColorGrading.cpp +++ b/filament/src/ColorGrading.cpp @@ -52,6 +52,8 @@ struct ColorGrading::BuilderDetails { ColorGrading::QualityLevel quality = QualityLevel::MEDIUM; ToneMapping toneMapping = ToneMapping::ACES_LEGACY; + // Luminance scaling + bool luminanceScaling = false; // Exposure float exposure = 0.0f; // White balance @@ -88,6 +90,7 @@ struct ColorGrading::BuilderDetails { // Note: Do NOT compare hasAdjustments return quality == rhs.quality && toneMapping == rhs.toneMapping && + luminanceScaling == rhs.luminanceScaling && exposure == rhs.exposure && whiteBalance == rhs.whiteBalance && outRed == rhs.outRed && @@ -127,6 +130,11 @@ ColorGrading::Builder& ColorGrading::Builder::toneMapping(ToneMapping toneMappin return *this; } +ColorGrading::Builder& ColorGrading::Builder::luminanceScaling(bool luminanceScaling) noexcept { + mImpl->luminanceScaling = luminanceScaling; + return *this; +} + ColorGrading::Builder& ColorGrading::Builder::exposure(float exposure) noexcept { mImpl->exposure = exposure; return *this; @@ -273,7 +281,8 @@ mat3f selectColorGradingTransformIn(ColorGrading::ToneMapping toneMapping) { case ColorGrading::ToneMapping::ACES: return sRGB_to_AP1; case ColorGrading::ToneMapping::FILMIC: - case ColorGrading::ToneMapping::EVILS: + case ColorGrading::ToneMapping::RESERVED: + case ColorGrading::ToneMapping::DISPLAY_RANGE: return mat3f{}; // stay in sRGB default: return sRGB_to_REC2020; @@ -286,7 +295,8 @@ mat3f selectColorGradingTransformOut(ColorGrading::ToneMapping toneMapping) { case ColorGrading::ToneMapping::ACES: return AP1_to_sRGB; case ColorGrading::ToneMapping::FILMIC: - case ColorGrading::ToneMapping::EVILS: + case ColorGrading::ToneMapping::RESERVED: + case ColorGrading::ToneMapping::DISPLAY_RANGE: return mat3f{}; // stay in sRGB default: return REC2020_to_sRGB; @@ -303,6 +313,16 @@ float3 selectLuminanceTransform(ColorGrading::ToneMapping toneMapping) { } } +float3 selectLuminanceScalingTransform(ColorGrading::ToneMapping toneMapping) { + switch (toneMapping) { + case ColorGrading::ToneMapping::ACES_LEGACY: + case ColorGrading::ToneMapping::ACES: + return LUMA_AP1; + default: + return LUMA_HK_REC709; + } +} + UTILS_ALWAYS_INLINE inline constexpr float3 channelMixer(float3 v, float3 r, float3 g, float3 b) { return {dot(v, r), dot(v, g), dot(v, b)}; @@ -379,6 +399,39 @@ inline float3 curves(float3 v, float3 shadowGamma, float3 midPoint, float3 highl }; } +//------------------------------------------------------------------------------ +// Luminance scaling +//------------------------------------------------------------------------------ + +static float3 luminanceScaling( + float3 x, ColorTransform toneMapper, float3 luminanceWeights) noexcept { + + // Troy Sobotka, 2021, "EVILS - Exposure Value Invariant Luminance Scaling" + // https://colab.research.google.com/drive/1iPJzNNKR7PynFmsqSnQm3bCZmQ3CvAJ-#scrollTo=psU43hb-BLzB + + float luminanceIn = dot(x, luminanceWeights); + + // TODO: We could optimize for the case of single-channel luminance + float luminanceOut = toneMapper(luminanceIn).x; + + float peak = max(x); + float3 chromaRatio = max(x / peak, 0.0f); + + float chromaRatioLuminance = dot(chromaRatio, luminanceWeights); + + float3 maxReserves = 1.0f - chromaRatio; + float maxReservesLuminance = dot(maxReserves, luminanceWeights); + + float luminanceDifference = std::max(luminanceOut - chromaRatioLuminance, 0.0f); + float scaledLuminanceDifference = + luminanceDifference / std::max(maxReservesLuminance, std::numeric_limits::min()); + + float chromaScale = (luminanceOut - luminanceDifference) / + std::max(chromaRatioLuminance, std::numeric_limits::min()); + + return chromaScale * chromaRatio + scaledLuminanceDifference * maxReserves; +} + //------------------------------------------------------------------------------ // Quality //------------------------------------------------------------------------------ @@ -435,8 +488,8 @@ ColorTransform selectToneMapping(ColorGrading::ToneMapping toneMapping) { return tonemap::ACES; case ColorGrading::ToneMapping::FILMIC: return tonemap::Filmic; - case ColorGrading::ToneMapping::EVILS: - return tonemap::EVILS; + case ColorGrading::ToneMapping::RESERVED: + return tonemap::Linear; case ColorGrading::ToneMapping::REINHARD: return tonemap::Reinhard; case ColorGrading::ToneMapping::DISPLAY_RANGE: @@ -452,6 +505,7 @@ struct Config { mat3f colorGradingTransformIn; mat3f colorGradingTransformOut; float3 luminanceTransform; + float3 luminanceScalingTransform; ColorTransform linearToLogTransform; ColorTransform logToLinearTransform; ColorTransform toneMapper; @@ -474,14 +528,15 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { utils::SpinLock configLock; { std::lock_guard lock(configLock); - c.colorGradingTransformIn = selectColorGradingTransformIn(builder->toneMapping); - c.colorGradingTransformOut = selectColorGradingTransformOut(builder->toneMapping); - c.luminanceTransform = selectLuminanceTransform(builder->toneMapping); - c.linearToLogTransform = selectLinearToLogTransform(builder->toneMapping); - c.logToLinearTransform = selectLogToLinearTransform(builder->toneMapping); - c.toneMapper = selectToneMapping(builder->toneMapping); - c.lutDimension = selectLutDimension(builder->quality); - c.adaptationTransform = adaptationTransform(builder->whiteBalance); + c.colorGradingTransformIn = selectColorGradingTransformIn(builder->toneMapping); + c.colorGradingTransformOut = selectColorGradingTransformOut(builder->toneMapping); + c.luminanceTransform = selectLuminanceTransform(builder->toneMapping); + c.luminanceScalingTransform = selectLuminanceScalingTransform(builder->toneMapping); + c.linearToLogTransform = selectLinearToLogTransform(builder->toneMapping); + c.logToLinearTransform = selectLogToLinearTransform(builder->toneMapping); + c.toneMapper = selectToneMapping(builder->toneMapping); + c.lutDimension = selectLutDimension(builder->quality); + c.adaptationTransform = adaptationTransform(builder->whiteBalance); } size_t lutElementCount = c.lutDimension * c.lutDimension * c.lutDimension; @@ -574,7 +629,11 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { } // Tone mapping - v = config.toneMapper(v); + if (builder->luminanceScaling) { + v = luminanceScaling(v, config.toneMapper, config.luminanceScalingTransform); + } else { + v = config.toneMapper(v); + } // Convert to output color space // TODO: allow to customize the output color space, diff --git a/filament/src/ToneMapping.cpp b/filament/src/ToneMapping.cpp index 34610188a6..74b51aa220 100644 --- a/filament/src/ToneMapping.cpp +++ b/filament/src/ToneMapping.cpp @@ -188,8 +188,19 @@ float3 ACES_Legacy(float3 x) noexcept { return aces::ACES(x, 1.0f / 0.6f); } -float genericTonemap(float x, float contrast, float shoulder, - float midGreyIn, float midGreyOut, float hdrMax) noexcept { +// TODO: These constants were chosen to match our ACES tone mappers as closely as possible +// in terms of compression. We should expose these parameters to users via an API. +// We must however carefully validate exposed parameters as it is easy to get the +// generic tonemapper to produce invalid curves. +// TODO: Expose this as a public tone mapper +float genericTonemap( + float x, + float contrast = 1.6f, + float shoulder = 1.0f, + float midGreyIn = 0.18f, + float midGreyOut = 0.227f, + float hdrMax = 64.0f +) noexcept { // Lottes, 2016,"Advanced Techniques and Optimization of VDR Color Pipelines" // https://gpuopen.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf float mc = std::pow(midGreyIn, contrast); @@ -210,46 +221,6 @@ float genericTonemap(float x, float contrast, float shoulder, return saturate(xc / (std::pow(xc, shoulder) * b + c)); } -constexpr float luminance(float3 v) noexcept { - return dot(v, LUMA_HK_REC709); -} - -float3 EVILS(float3 x) noexcept { - // Troy Sobotka, 2021, "EVILS - Exposure Value Invariant Luminance Scaling" - // https://colab.research.google.com/drive/1iPJzNNKR7PynFmsqSnQm3bCZmQ3CvAJ-#scrollTo=psU43hb-BLzB - - // TODO: These constants were chosen to match our ACES tone mappers as closely as possible - // in terms of compression. We should expose these parameters to users via an API. - // We must however carefully validate exposed parameters as it is easy to get the - // generic tonemapper to produce invalid curves. - constexpr float contrast = 1.6f; - constexpr float shoulder = 1.0f; - constexpr float midGreyIn = 0.18f; - constexpr float midGreyOut = 0.227f; - constexpr float hdrMax = 64.0f; - - // We assume an input compatible with Rec.709 luminance weights - float luminanceIn = luminance(x); - float luminanceOut = genericTonemap(luminanceIn, contrast, shoulder, midGreyIn, midGreyOut, hdrMax); - - float peak = max(x); - float3 chromaRatio = max(x / peak, 0.0f); - - float chromaRatioLuminance = luminance(chromaRatio); - - float3 maxReserves = 1.0f - chromaRatio; - float maxReservesLuminance = luminance(maxReserves); - - float luminanceDifference = std::max(luminanceOut - chromaRatioLuminance, 0.0f); - float scaledLuminanceDifference = - luminanceDifference / std::max(maxReservesLuminance, std::numeric_limits::min()); - - float chromaScale = (luminanceOut - luminanceDifference) / - std::max(chromaRatioLuminance, std::numeric_limits::min()); - - return chromaScale * chromaRatio + scaledLuminanceDifference * maxReserves; -} - float3 DisplayRange(float3 x) noexcept { // 16 debug colors + 1 duplicated at the end for easy indexing diff --git a/filament/src/ToneMapping.h b/filament/src/ToneMapping.h index f4073ee381..6502f81610 100644 --- a/filament/src/ToneMapping.h +++ b/filament/src/ToneMapping.h @@ -67,8 +67,6 @@ float3 ACES(float3 x) noexcept; float3 ACES_Legacy(float3 x) noexcept; -float3 EVILS(float3 x) noexcept; - /** * Converts the input HDR RGB color into one of 16 debug colors that represent * the pixel's exposure. When the output is cyan, the input color represents diff --git a/libs/viewer/include/viewer/Settings.h b/libs/viewer/include/viewer/Settings.h index 578f17ddcd..65f1b9d9b3 100644 --- a/libs/viewer/include/viewer/Settings.h +++ b/libs/viewer/include/viewer/Settings.h @@ -98,6 +98,7 @@ struct ColorGradingSettings { bool enabled = true; filament::ColorGrading::QualityLevel quality = filament::ColorGrading::QualityLevel::MEDIUM; ToneMapping toneMapping = ToneMapping::ACES_LEGACY; + bool luminanceScaling = false; float exposure = 0.0f; float temperature = 0.0f; float tint = 0.0f; diff --git a/libs/viewer/src/Settings.cpp b/libs/viewer/src/Settings.cpp index 91f845f92c..93de1a75e6 100644 --- a/libs/viewer/src/Settings.cpp +++ b/libs/viewer/src/Settings.cpp @@ -186,7 +186,7 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ToneMapp else if (0 == compare(tokens[i], jsonChunk, "ACES_LEGACY")) { *out = ToneMapping::ACES_LEGACY; } else if (0 == compare(tokens[i], jsonChunk, "ACES")) { *out = ToneMapping::ACES; } else if (0 == compare(tokens[i], jsonChunk, "FILMIC")) { *out = ToneMapping::FILMIC; } - else if (0 == compare(tokens[i], jsonChunk, "EVILS")) { *out = ToneMapping::EVILS; } + else if (0 == compare(tokens[i], jsonChunk, "RESERVED")) { *out = ToneMapping::RESERVED; } else if (0 == compare(tokens[i], jsonChunk, "REINHARD")) { *out = ToneMapping::REINHARD; } else if (0 == compare(tokens[i], jsonChunk, "DISPLAY_RANGE")) { *out = ToneMapping::DISPLAY_RANGE; } else { @@ -279,6 +279,8 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ColorGra i = parse(tokens, i + 1, jsonChunk, &out->quality); } else if (compare(tok, jsonChunk, "toneMapping") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->toneMapping); + } else if (compare(tok, jsonChunk, "luminanceScaling") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->luminanceScaling); } else if (compare(tok, jsonChunk, "exposure") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->exposure); } else if (compare(tok, jsonChunk, "temperature") == 0) { @@ -980,6 +982,7 @@ ColorGrading* createColorGrading(const ColorGradingSettings& settings, Engine* e .saturation(settings.saturation) .curves(settings.gamma, settings.midPoint, settings.scale) .toneMapping(settings.toneMapping) + .luminanceScaling(settings.luminanceScaling) .build(*engine); } @@ -1049,7 +1052,7 @@ static std::ostream& operator<<(std::ostream& out, ToneMapping in) { case ToneMapping::ACES_LEGACY: return out << "\"ACES_LEGACY\""; case ToneMapping::ACES: return out << "\"ACES\""; case ToneMapping::FILMIC: return out << "\"FILMIC\""; - case ToneMapping::EVILS: return out << "\"EVILS\""; + case ToneMapping::RESERVED: return out << "\"RESERVED\""; case ToneMapping::REINHARD: return out << "\"REINHARD\""; case ToneMapping::DISPLAY_RANGE: return out << "\"DISPLAY_RANGE\""; } @@ -1089,6 +1092,7 @@ static std::ostream& operator<<(std::ostream& out, const ColorGradingSettings& i << "\"enabled\": " << to_string(in.enabled) << ",\n" << "\"quality\": " << (in.quality) << ",\n" << "\"toneMapping\": " << (in.toneMapping) << ",\n" + << "\"luminanceScaling\": " << (in.luminanceScaling) << ",\n" << "\"exposure\": " << (in.exposure) << ",\n" << "\"temperature\": " << (in.temperature) << ",\n" << "\"tint\": " << (in.tint) << ",\n" @@ -1347,6 +1351,7 @@ bool ColorGradingSettings::operator==(const ColorGradingSettings &rhs) const { return enabled == rhs.enabled && quality == rhs.quality && toneMapping == rhs.toneMapping && + luminanceScaling == rhs.luminanceScaling && exposure == rhs.exposure && temperature == rhs.temperature && tint == rhs.tint && diff --git a/libs/viewer/src/SimpleViewer.cpp b/libs/viewer/src/SimpleViewer.cpp index a87c315738..ffc8b97333 100644 --- a/libs/viewer/src/SimpleViewer.cpp +++ b/libs/viewer/src/SimpleViewer.cpp @@ -151,8 +151,9 @@ static void colorGradingUI(Settings& settings, float* rangePlot, float* curvePlo int toneMapping = (int) colorGrading.toneMapping; ImGui::Combo("Tone-mapping", &toneMapping, - "Linear\0ACES (legacy)\0ACES\0Filmic\0EVILS\0Reinhard\0Display Range\0\0"); + "Linear\0ACES (legacy)\0ACES\0Filmic\0Reserved\0Reinhard\0Display Range\0\0"); colorGrading.toneMapping = (decltype(colorGrading.toneMapping)) toneMapping; + ImGui::Checkbox("Luminance scaling", &colorGrading.luminanceScaling); ImGui::SliderFloat("Exposure", &colorGrading.exposure, -10.0f, 10.0f); diff --git a/libs/viewer/tests/test_settings.cpp b/libs/viewer/tests/test_settings.cpp index 3e106b3ead..3273fb8f8d 100644 --- a/libs/viewer/tests/test_settings.cpp +++ b/libs/viewer/tests/test_settings.cpp @@ -37,6 +37,7 @@ static const char* JSON_TEST_DEFAULTS = R"TXT( "enabled": true, "quality": "MEDIUM", "toneMapping": "ACES_LEGACY", + "luminanceScaling": false, "exposure": 0, "temperature": 0, "tint": 0, diff --git a/samples/material_sandbox.cpp b/samples/material_sandbox.cpp index c7a70b4064..f3b2c53a62 100644 --- a/samples/material_sandbox.cpp +++ b/samples/material_sandbox.cpp @@ -716,7 +716,8 @@ static void gui(filament::Engine* engine, filament::View*) { ImGui::Indent(); ImGui::Checkbox("Enabled##colorGrading", ¶ms.colorGrading); ImGui::Combo("Tone-mapping", &colorGrading.toneMapping, - "Linear\0ACES (legacy)\0ACES\0Filmic\0EVILS\0Reinhard\0Display Range\0\0"); + "Linear\0ACES (legacy)\0ACES\0Filmic\0Reserved\0Reinhard\0Display Range\0\0"); + ImGui::Checkbox("Luminance scaling", &colorGrading.luminanceScaling); if (ImGui::CollapsingHeader("While balance")) { ImGui::SliderInt("Temperature", &colorGrading.temperature, -100, 100); ImGui::SliderInt("Tint", &colorGrading.tint, -100, 100); @@ -984,6 +985,7 @@ static void preRender(filament::Engine* engine, filament::View* view, filament:: .saturation(options.saturation) .curves(options.gamma, options.midPoint, options.scale) .toneMapping(static_cast(options.toneMapping)) + .luminanceScaling(options.luminanceScaling) .build(*engine); if (g_colorGrading) { diff --git a/samples/material_sandbox.h b/samples/material_sandbox.h index 2e6c258db9..022966fe0d 100644 --- a/samples/material_sandbox.h +++ b/samples/material_sandbox.h @@ -62,6 +62,7 @@ using namespace filament; struct ColorGradingOptions { int toneMapping = static_cast(ColorGrading::ToneMapping::ACES_LEGACY); + bool luminanceScaling = false; int temperature = 0; int tint = 0; math::float3 outRed{1.0f, 0.0f, 0.0f}; @@ -88,6 +89,7 @@ struct ColorGradingOptions { bool operator==(const ColorGradingOptions &rhs) const { return toneMapping == rhs.toneMapping && + luminanceScaling == rhs.luminanceScaling && temperature == rhs.temperature && outRed == rhs.outRed && outGreen == rhs.outGreen && diff --git a/web/filament-js/jsenums.cpp b/web/filament-js/jsenums.cpp index de0524ce38..ed7037aad7 100644 --- a/web/filament-js/jsenums.cpp +++ b/web/filament-js/jsenums.cpp @@ -164,7 +164,7 @@ enum_("ColorGrading$ToneMapping") .value("ACES_LEGACY", ColorGrading::ToneMapping::ACES_LEGACY) .value("ACES", ColorGrading::ToneMapping::ACES) .value("FILMIC", ColorGrading::ToneMapping::FILMIC) - .value("EVILS", ColorGrading::ToneMapping::EVILS) + .value("RESERVED", ColorGrading::ToneMapping::RESERVED) .value("REINHARD", ColorGrading::ToneMapping::REINHARD) .value("DISPLAY_RANGE", ColorGrading::ToneMapping::DISPLAY_RANGE);