From 8a8b74a6e925135fab8d6797ae51da2511d2d81c Mon Sep 17 00:00:00 2001 From: rbarrand Date: Mon, 11 Oct 2021 19:19:17 -0700 Subject: [PATCH] Finalize shaper implementation. Refactor color grading functions. Signed-off-by: rbarrand --- .../Common/Assets/Passes/HDRColorGrading.pass | 4 +- .../PostProcessing/HDRColorGradingCommon.azsl | 129 +++++++++++++ .../Shaders/ColorGrading/LutGeneration.azsl | 178 +++++------------- .../PostProcessing/HDRColorGrading.azsl | 123 +----------- .../Source/ColorGrading/LutGenerationPass.cpp | 4 - .../Source/ColorGrading/LutGenerationPass.h | 4 +- .../PostProcessing/HDRColorGradingPass.cpp | 4 +- .../EditorHDRColorGradingComponent.cpp | 11 ++ 8 files changed, 196 insertions(+), 261 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PostProcessing/HDRColorGradingCommon.azsl diff --git a/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass index adcd43ce83..c043d1e72b 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass @@ -73,7 +73,7 @@ }, { "Name": "m_colorGradingPreSaturation", - "Value": 1.0 // -100 ... 100 + "Value": 1.0 // 0 ... 2 }, { "Name": "m_colorFilterIntensity", @@ -101,7 +101,7 @@ }, { "Name": "m_colorGradingPostSaturation", - "Value": 1.0 // -100 ... 100 + "Value": 1.0 // 0 ... 2 }, { "Name": "m_smhShadowsStart", diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PostProcessing/HDRColorGradingCommon.azsl b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PostProcessing/HDRColorGradingCommon.azsl new file mode 100644 index 0000000000..501aac7e79 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PostProcessing/HDRColorGradingCommon.azsl @@ -0,0 +1,129 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli> +#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli> +#include <3rdParty/Features/PostProcessing/KelvinToRgb.azsli> + +static const float FloatEpsilon = 1.192092896e-07; // 1.0 + FloatEpsilon != 1.0, smallest positive float +static const float FloatMin = FLOAT_32_MIN; // Min float number that is positive +static const float FloatMax = FLOAT_32_MAX; // Max float number representable + +static const float AcesCcMidGrey = 0.4135884; + +float SaturateWithEpsilon(float value) +{ + return clamp(value, FloatEpsilon, 1.0f); +} + +// Below are the color grading functions. These expect the frame color to be in ACEScg space. +// Note that some functions may have some quirks in their implementation and is subject to change. +float3 ColorGradePostExposure (float3 frameColor, float exposure) +{ + frameColor *= pow(2.0f, exposure); + return frameColor; +} + +// The contrast equation is performed in ACEScc (logarithmic) color space. +float3 ColorGradingContrast (float3 frameColor, float midgrey, float amount) +{ + const float contrastAdjustment = amount * 0.01f + 1.0f; + frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScg, ColorSpaceId::ACEScc); + frameColor = (frameColor - midgrey) * contrastAdjustment + midgrey; + return frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScc, ColorSpaceId::ACEScg); +} + +// The swatchColor param expects a linear RGB value. +float3 ColorGradeColorFilter (float3 frameColor, float3 swatchColor, float alpha, float colorFilterIntensity) +{ + swatchColor = TransformColor(swatchColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + swatchColor *= pow(2.0f, colorFilterIntensity); + const float3 frameAdjust = frameColor * swatchColor; + return frameColor = lerp(frameColor, frameAdjust, alpha); +} + +float3 ColorGradeHueShift (float3 frameColor, float amount) +{ + float3 frameHsv = RgbToHsv(frameColor); + const float hue = frameHsv.x + amount; + frameHsv.x = RotateHue(hue, 0.0, 1.0); + return HsvToRgb(frameHsv); +} + +float3 ColorGradeSaturation (float3 frameColor, float control) +{ + const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + return (frameColor - vLuminance) * control + vLuminance; +} + +float3 ColorGradeKelvinColorTemp(float3 frameColor, float kelvin) +{ + const float3 kColor = TransformColor(KelvinToRgb(kelvin), ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float luminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + const float3 resHsl = RgbToHsl(frameColor.rgb * kColor.rgb); // Apply Kelvin color and convert to HSL + return HslToRgb(float3(resHsl.xy, luminance)); // Preserve luminance +} + +// pow(f, e) won't work if f is negative, or may cause inf/NAN. +float3 NoNanPow(float3 base, float3 power) +{ + return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power); +} + +float3 ColorGradeSplitTone ( + float3 frameColor, + float balance, + float weight, + float3 splitToneShadowsColor, + float3 splitToneHighlightsColor) +{ + float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2); + const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance); + const float3 shadows = lerp(0.5, splitToneShadowsColor, 1.0 - t); + const float3 highlights = lerp(0.5, splitToneHighlightsColor, t); + frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows); + frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights); + frameSplitTone = NoNanPow(frameSplitTone, 2.2); + return lerp(frameColor.rgb, frameSplitTone.rgb, weight); +} + +float3 ColorGradeChannelMixer ( + float3 frameColor, + float3 channelMixingRed, + float3 channelMixingGreen, + float3 channelMixingBlue) +{ + return mul(float3x3(channelMixingRed, + channelMixingGreen, + channelMixingBlue), + frameColor); +} + +float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd, + float highlightsStart, float highlightsEnd, float weight, + float4 shadowsColor, float4 midtonesColor, float4 highlightsColor) +{ + const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float3 midtonesColorACEScg = TransformColor(midtonesColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float3 highlightsColorACEScg = TransformColor(highlightsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + + const float cLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + const float shadowsWeight = 1.0 - smoothstep(shadowsStart, shadowsEnd, cLuminance); + const float highlightsWeight = smoothstep(highlightsStart, highlightsEnd, cLuminance); + const float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight; + + const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight + + frameColor * midtonesColorACEScg * midtonesWeight + + frameColor * highlightsColorACEScg * highlightsWeight; + return lerp(frameColor.rgb, frameSmh.rgb, weight); +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.azsl index ead9fe5739..d740ea8e1c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/ColorGrading/LutGeneration.azsl @@ -14,31 +14,15 @@ #include -#include #include #include -#include -#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli> -#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli> -#include <3rdParty/Features/PostProcessing/KelvinToRgb.azsli> - -static const float FloatEpsilon = 1.192092896e-07; // 1.0 + FloatEpsilon != 1.0, smallest positive float -static const float FloatMin = FLOAT_32_MIN; // Min float number that is positive -static const float FloatMax = FLOAT_32_MAX; // Max float number representable - -static const float AcesCcMidGrey = 0.4135884; +#include float3 convert2Dto3DLutCoords(float2 uv, float width, float height) { - //uint adjustedU = uv.x * (height-1)*(height-1); - //uint2 adjustedUv = uint2(uv.x * height*height, uv.y * (height-1)); - //uint3 coords = uint3(adjustedUv.x%height, adjustedUv.y, adjustedU/(height-1)); - //float3 coords = float3(clamp(((adjustedUv.x-1)%height+1), 0, height), adjustedUv.y, (int)(adjustedUv.x/height)); - - float2 adjustedUv = float2(uv.x * height*height, uv.y * height); - float3 coords = float3(adjustedUv.x%height, uv.x*height, adjustedUv.y); + float2 adjustedUv = float2(uv.x * width, uv.y * height); + float3 coords = float3(adjustedUv.x%height, 0.5 + int(adjustedUv.x/height), adjustedUv.y); return coords/height; - //return float3(uv.x, uv.x, uv.y); } enum class LutResolution @@ -111,110 +95,27 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback float4 m_smhHighlightsColor; } -float SaturateWithEpsilon(float value) +float3 ColorGrade(float3 linearColor) { - return clamp(value, FloatEpsilon, 1.0f); -} - -// Below are the color grading functions. These expect the frame color to be in ACEScg space. -// Note that some functions may have some quirks in their implementation and is subject to change. -float3 ColorGradePostExposure (float3 frameColor, float exposure) -{ - frameColor *= pow(2.0f, exposure); - return frameColor; -} - -// The contrast equation is performed in ACEScc (logarithmic) color space. -float3 ColorGradingContrast (float3 frameColor, float midgrey, float amount) -{ - const float contrastAdjustment = amount * 0.01f + 1.0f; - frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScg, ColorSpaceId::ACEScc); - frameColor = (frameColor - midgrey) * contrastAdjustment + midgrey; - return frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScc, ColorSpaceId::ACEScg); -} - -// The swatchColor param expects a linear RGB value. -float3 ColorGradeColorFilter (float3 frameColor, float3 swatchColor, float alpha) -{ - swatchColor = TransformColor(swatchColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - swatchColor *= pow(2.0f, PassSrg::m_colorFilterIntensity); - const float3 frameAdjust = frameColor * swatchColor; - return frameColor = lerp(frameColor, frameAdjust, alpha); -} - -float3 ColorGradeHueShift (float3 frameColor, float amount) -{ - float3 frameHsv = RgbToHsv(frameColor); - const float hue = frameHsv.x + amount; - frameHsv.x = RotateHue(hue, 0.0, 1.0); - return HsvToRgb(frameHsv); -} - -float3 ColorGradeSaturation (float3 frameColor, float control) -{ - const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::LinearSRGB); - //const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - return (frameColor - vLuminance) * control + vLuminance; -} - -float3 ColorGradeKelvinColorTemp(float3 frameColor, float kelvin) -{ - const float3 kColor = TransformColor(KelvinToRgb(kelvin), ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float luminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - const float3 resHsl = RgbToHsl(frameColor.rgb * kColor.rgb); // Apply Kelvin color and convert to HSL - return HslToRgb(float3(resHsl.xy, luminance)); // Preserve luminance -} - -// pow(f, e) won't work if f is negative, or may cause inf/NAN. -float3 NoNanPow(float3 base, float3 power) -{ - return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power); -} - -float3 ColorGradeSplitTone (float3 frameColor, float balance, float weight) -{ - float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2); - const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance); - const float3 shadows = lerp(0.5, PassSrg::m_splitToneShadowsColor.rgb, 1.0 - t); - const float3 highlights = lerp(0.5, PassSrg::m_splitToneHighlightsColor.rgb, t); - frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows); - frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights); - frameSplitTone = NoNanPow(frameSplitTone, 2.2); - return lerp(frameColor.rgb, frameSplitTone.rgb, weight); -} - -float3 ColorGradeChannelMixer (float3 frameColor) -{ - return mul(float3x3(PassSrg::m_channelMixingRed.rgb, - PassSrg::m_channelMixingGreen.rgb, - PassSrg::m_channelMixingBlue.rgb), - frameColor); -} - -float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd, - float highlightsStart, float highlightsEnd, float weight, - float4 shadowsColor, float4 midtonesColor, float4 highlightsColor) -{ - const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float3 midtonesColorACEScg = TransformColor(midtonesColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float3 highlightsColorACEScg = TransformColor(highlightsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - - const float cLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - const float shadowsWeight = 1.0 - smoothstep(shadowsStart, shadowsEnd, cLuminance); - const float highlightsWeight = smoothstep(highlightsStart, highlightsEnd, cLuminance); - const float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight; - - const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight + - frameColor * midtonesColorACEScg * midtonesWeight + - frameColor * highlightsColorACEScg * highlightsWeight; - return lerp(frameColor.rgb, frameSmh.rgb, weight); -} - -float3 ColorGrade(float3 frameColor) -{ - frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation); - frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation); - return frameColor.rgb; + float3 color = TransformColor(linearColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + color = ColorGradePostExposure(color, PassSrg::m_colorGradingExposure); + color = ColorGradeKelvinColorTemp(color, PassSrg::m_whiteBalanceKelvin); + color = ColorGradingContrast(color, AcesCcMidGrey, PassSrg::m_colorGradingContrast); + color = ColorGradeColorFilter(color, PassSrg::m_colorFilterSwatch.rgb, + PassSrg::m_colorFilterMultiply, PassSrg::m_colorFilterIntensity); + color = max(color, 0.0); + color = ColorGradeSaturation(color, PassSrg::m_colorGradingPreSaturation); + color = ColorGradeSplitTone(color, PassSrg::m_splitToneBalance, PassSrg::m_splitToneWeight, + PassSrg::m_splitToneShadowsColor, PassSrg::m_splitToneHighlightsColor); + color = ColorGradeChannelMixer(color, PassSrg::m_channelMixingRed, PassSrg::m_channelMixingGreen, PassSrg::m_channelMixingBlue); + color = max(color, 0.0); + color = ColorGradeShadowsMidtonesHighlights(color, PassSrg::m_smhShadowsStart, PassSrg::m_smhShadowsEnd, + PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhWeight, + PassSrg::m_smhShadowsColor, PassSrg::m_smhMidtonesColor, PassSrg::m_smhHighlightsColor); + color = ColorGradeHueShift(color, PassSrg::m_colorGradingHueShift); + color = ColorGradeSaturation(color, PassSrg::m_colorGradingPostSaturation); + color = TransformColor(color, ColorSpaceId::ACEScg, ColorSpaceId::LinearSRGB); + return max(color.rgb, 0.0); } struct PSOutput @@ -222,11 +123,6 @@ struct PSOutput float4 m_lutOutput : SV_Target0; }; -float3 InverseGamma(float3 color) -{ - return pow(color, 2.2); -} - float3 GetSourceLutLinearColor(float3 baseColor, Texture3D sourceLut, ShaperType shaperType, float shaperBias, float shaperScale) { // Convert from reference linearColor to the lutCoordinate for this Lut @@ -239,7 +135,7 @@ float3 GetSourceLutLinearColor(float3 baseColor, Texture3D sourceLut, Sh float3 coordScale = (outputDimensions - 1.0) / outputDimensions; lutCoord = (lutCoord * coordScale) + coordBias; - float3 lutColor = sourceLut.SampleLevel(PassSrg::PointSampler, lutCoord, 0).rgb; + float3 lutColor = sourceLut.SampleLevel(PassSrg::LinearSampler, lutCoord, 0).rgb; // Convert to linear float3 linearColor = ShaperToLinear(lutColor, shaperType, shaperBias, shaperScale); return linearColor; @@ -251,7 +147,6 @@ PSOutput MainPS(VSOutput IN) PSOutput OUT; - uint3 lutDimensions; float3 baseCoords = float3(0.0, 0.0, 0.0); float3 lutColor = float3(0.0, 0.0, 0.0); LutResolution lutRes = (LutResolution)PassSrg::m_lutResolution; @@ -259,9 +154,9 @@ PSOutput MainPS(VSOutput IN) { case LutResolution::Lut16x16x16: { + // This seems correct. baseCoords = convert2Dto3DLutCoords(IN.m_texCoord, 256, 16); lutColor = PassSrg::m_identityLut16x16x16.Sample(PassSrg::PointSampler, baseCoords, 0.0).rgb; - //lutColor = TransformColor(lutColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); break; } case LutResolution::Lut32x32x32: @@ -272,16 +167,27 @@ PSOutput MainPS(VSOutput IN) } case LutResolution::Lut64x64x64: { + // This doesn't look right. baseCoords = convert2Dto3DLutCoords(IN.m_texCoord, 4096, 64); - lutColor = PassSrg::m_identityLut64x64x64.Sample(PassSrg::PointSampler, baseCoords, 0.0).rgb; + float3 baseColor = ShaperToLinear(baseCoords, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale); + //lutColor = PassSrg::m_identityLut64x64x64.Sample(PassSrg::PointSampler, baseCoords, 0.0).rgb; + lutColor = GetSourceLutLinearColor( + baseColor, + PassSrg::m_identityLut64x64x64, + shaperType, + PassSrg::m_shaperBias, + PassSrg::m_shaperScale + ); break; } } - //float3 lutColor = ShaperToLinear(baseCoords, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale); - float3 gradedColor = float4(ColorGrade(lutColor), 1.0); - //float3 finalColor = LinearToShaper(gradedColor, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale); - gradedColor = TransformColor(gradedColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - OUT.m_lutOutput = float4(gradedColor, 1.0); + // color grade in linear sapce + float3 gradedColor = ColorGrade(lutColor); + + float3 shapedColor = LinearToShaper(gradedColor, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale); + float3 clampedColor = saturate(gradedColor); + + OUT.m_lutOutput = float4(clampedColor, 1.0); return OUT; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl index cfa149f0d5..9225735e85 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl @@ -12,18 +12,7 @@ #include #include - -#include -#include -#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli> -#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli> -#include <3rdParty/Features/PostProcessing/KelvinToRgb.azsli> - -static const float FloatEpsilon = 1.192092896e-07; // 1.0 + FloatEpsilon != 1.0, smallest positive float -static const float FloatMin = FLOAT_32_MIN; // Min float number that is positive -static const float FloatMax = FLOAT_32_MAX; // Max float number representable - -static const float AcesCcMidGrey = 0.4135884; +#include ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback { @@ -71,122 +60,26 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback float4 m_smhHighlightsColor; } -float SaturateWithEpsilon(float value) -{ - return clamp(value, FloatEpsilon, 1.0f); -} - -// Below are the color grading functions. These expect the frame color to be in ACEScg space. -// Note that some functions may have some quirks in their implementation and is subject to change. -float3 ColorGradePostExposure (float3 frameColor, float exposure) -{ - frameColor *= pow(2.0f, exposure); - return frameColor; -} - -// The contrast equation is performed in ACEScc (logarithmic) color space. -float3 ColorGradingContrast (float3 frameColor, float midgrey, float amount) -{ - const float contrastAdjustment = amount * 0.01f + 1.0f; - frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScg, ColorSpaceId::ACEScc); - frameColor = (frameColor - midgrey) * contrastAdjustment + midgrey; - return frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScc, ColorSpaceId::ACEScg); -} - -// The swatchColor param expects a linear RGB value. -float3 ColorGradeColorFilter (float3 frameColor, float3 swatchColor, float alpha) -{ - swatchColor = TransformColor(swatchColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - swatchColor *= pow(2.0f, PassSrg::m_colorFilterIntensity); - const float3 frameAdjust = frameColor * swatchColor; - return frameColor = lerp(frameColor, frameAdjust, alpha); -} - -float3 ColorGradeHueShift (float3 frameColor, float amount) -{ - float3 frameHsv = RgbToHsv(frameColor); - const float hue = frameHsv.x + amount; - frameHsv.x = RotateHue(hue, 0.0, 1.0); - return HsvToRgb(frameHsv); -} - -float3 ColorGradeSaturation (float3 frameColor, float control) -{ - const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - return (frameColor - vLuminance) * control + vLuminance; -} - -float3 ColorGradeKelvinColorTemp(float3 frameColor, float kelvin) -{ - const float3 kColor = TransformColor(KelvinToRgb(kelvin), ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float luminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - const float3 resHsl = RgbToHsl(frameColor.rgb * kColor.rgb); // Apply Kelvin color and convert to HSL - return HslToRgb(float3(resHsl.xy, luminance)); // Preserve luminance -} - -// pow(f, e) won't work if f is negative, or may cause inf/NAN. -float3 NoNanPow(float3 base, float3 power) -{ - return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power); -} - -float3 ColorGradeSplitTone (float3 frameColor, float balance, float weight) -{ - float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2); - const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance); - const float3 shadows = lerp(0.5, PassSrg::m_splitToneShadowsColor.rgb, 1.0 - t); - const float3 highlights = lerp(0.5, PassSrg::m_splitToneHighlightsColor.rgb, t); - frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows); - frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights); - frameSplitTone = NoNanPow(frameSplitTone, 2.2); - return lerp(frameColor.rgb, frameSplitTone.rgb, weight); -} - -float3 ColorGradeChannelMixer (float3 frameColor) -{ - return mul(float3x3(PassSrg::m_channelMixingRed.rgb, - PassSrg::m_channelMixingGreen.rgb, - PassSrg::m_channelMixingBlue.rgb), - frameColor); -} - -float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd, - float highlightsStart, float highlightsEnd, float weight, - float4 shadowsColor, float4 midtonesColor, float4 highlightsColor) -{ - const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float3 midtonesColorACEScg = TransformColor(midtonesColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - const float3 highlightsColorACEScg = TransformColor(highlightsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); - - const float cLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); - const float shadowsWeight = 1.0 - smoothstep(shadowsStart, shadowsEnd, cLuminance); - const float highlightsWeight = smoothstep(highlightsStart, highlightsEnd, cLuminance); - const float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight; - - const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight + - frameColor * midtonesColorACEScg * midtonesWeight + - frameColor * highlightsColorACEScg * highlightsWeight; - return lerp(frameColor.rgb, frameSmh.rgb, weight); -} - -float3 ColorGrade (float3 frameColor) +// perform color grading in ACEScg space +float3 ColorGrade(float3 frameColor) { frameColor = ColorGradePostExposure(frameColor, PassSrg::m_colorGradingExposure); frameColor = ColorGradeKelvinColorTemp(frameColor, PassSrg::m_whiteBalanceKelvin); frameColor = ColorGradingContrast(frameColor, AcesCcMidGrey, PassSrg::m_colorGradingContrast); frameColor = ColorGradeColorFilter(frameColor, PassSrg::m_colorFilterSwatch.rgb, - PassSrg::m_colorFilterMultiply); + PassSrg::m_colorFilterMultiply, PassSrg::m_colorFilterIntensity); frameColor = max(frameColor, 0.0); frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation); - frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneWeight); - frameColor = ColorGradeChannelMixer(frameColor); + frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneWeight, + PassSrg::m_splitToneShadowsColor, PassSrg::m_splitToneHighlightsColor); + frameColor = ColorGradeChannelMixer(frameColor, PassSrg::m_channelMixingRed, PassSrg::m_channelMixingGreen, PassSrg::m_channelMixingBlue); frameColor = max(frameColor, 0.0); frameColor = ColorGradeShadowsMidtonesHighlights(frameColor, PassSrg::m_smhShadowsStart, PassSrg::m_smhShadowsEnd, PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhWeight, PassSrg::m_smhShadowsColor, PassSrg::m_smhMidtonesColor, PassSrg::m_smhHighlightsColor); frameColor = ColorGradeHueShift(frameColor, PassSrg::m_colorGradingHueShift); frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation); - return frameColor.rgb; + return max(frameColor.rgb, 0.0); } PSOutput MainPS(VSOutput IN) diff --git a/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.cpp index f6d14e1f1b..81edb3887b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.cpp @@ -6,8 +6,6 @@ * */ -#pragma optimize("", off) - #include #include @@ -121,5 +119,3 @@ namespace AZ } // namespace Render } // namespace AZ - -#pragma optimize("", on) diff --git a/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.h b/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.h index 273d2aaa31..c9e439964c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/ColorGrading/LutGenerationPass.h @@ -20,6 +20,7 @@ namespace AZ { namespace Render { + // Performs color grading on an identity LUT strip class LutGenerationPass : public AZ::Render::HDRColorGradingPass { @@ -58,12 +59,11 @@ namespace AZ "m_identityLut16x16x16", "m_identityLut32x32x32", "m_identityLut64x64x64" }; + RHI::ShaderInputNameIndex m_lutResolutionIndex = "m_lutResolution"; RHI::ShaderInputNameIndex m_lutShaperTypeIndex = "m_shaperType"; RHI::ShaderInputNameIndex m_lutShaperBiasIndex = "m_shaperBias"; RHI::ShaderInputNameIndex m_lutShaperScaleIndex = "m_shaperScale"; - - bool m_isInitialized = false; }; } // namespace Render diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp index 62fff6b6fe..127f0f94a1 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp @@ -82,14 +82,14 @@ m_shaderResourceGroup->SetConstant(m_colorGradingExposureIndex, settings->GetColorGradingExposure()); m_shaderResourceGroup->SetConstant(m_colorGradingContrastIndex, settings->GetColorGradingContrast()); m_shaderResourceGroup->SetConstant(m_colorGradingHueShiftIndex, settings->GetColorGradingHueShift()); - m_shaderResourceGroup->SetConstant(m_colorGradingPreSaturationIndex, settings->GetColorGradingPreSaturation()); + m_shaderResourceGroup->SetConstant(m_colorGradingPreSaturationIndex, settings->GetColorGradingPreSaturation() * 0.01f + 1.0f); m_shaderResourceGroup->SetConstant(m_colorFilterIntensityIndex, settings->GetColorGradingFilterIntensity()); m_shaderResourceGroup->SetConstant(m_colorFilterMultiplyIndex, settings->GetColorGradingFilterMultiply()); m_shaderResourceGroup->SetConstant(m_whiteBalanceKelvinIndex, settings->GetWhiteBalanceKelvin()); m_shaderResourceGroup->SetConstant(m_whiteBalanceTintIndex, settings->GetWhiteBalanceTint()); m_shaderResourceGroup->SetConstant(m_splitToneBalanceIndex, settings->GetSplitToneBalance()); m_shaderResourceGroup->SetConstant(m_splitToneWeightIndex, settings->GetSplitToneWeight()); - m_shaderResourceGroup->SetConstant(m_colorGradingPostSaturationIndex, settings->GetColorGradingPostSaturation()); + m_shaderResourceGroup->SetConstant(m_colorGradingPostSaturationIndex, settings->GetColorGradingPostSaturation() * 0.01f + 1.0f); m_shaderResourceGroup->SetConstant(m_smhShadowsStartIndex, settings->GetSmhShadowsStart()); m_shaderResourceGroup->SetConstant(m_smhShadowsEndIndex, settings->GetSmhShadowsEnd()); m_shaderResourceGroup->SetConstant(m_smhHighlightsStartIndex, settings->GetSmhHighlightsStart()); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp index 6ecaa55212..1164738314 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp @@ -185,6 +185,13 @@ namespace AZ const char* LutAttachment = "LutOutput"; const AZStd::vector LutGenerationPassHierarchy{ "LutGenerationPass" }; + char resolvedOutputFilePath[AZ_MAX_PATH_LEN] = { 0 }; + AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(m_currentTiffFilePath.c_str(), resolvedOutputFilePath, AZ_MAX_PATH_LEN); + + AZStd::string lutGenerationCacheFolder; + AzFramework::StringFunc::Path::GetFolderPath(resolvedOutputFilePath, lutGenerationCacheFolder); + AZ::IO::SystemFile::CreateDir(lutGenerationCacheFolder.c_str()); + // capture frame AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect(); @@ -208,6 +215,10 @@ namespace AZ char resolvedOutputFilePath[AZ_MAX_PATH_LEN] = { 0 }; AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(m_currentLutFilePath.c_str(), resolvedOutputFilePath, AZ_MAX_PATH_LEN); + AZStd::string lutGenerationFolder; + AzFramework::StringFunc::Path::GetFolderPath(resolvedOutputFilePath, lutGenerationFolder); + AZ::IO::SystemFile::CreateDir(lutGenerationFolder.c_str()); + AZStd::vector pythonArgs { "--i", resolvedInputFilePath,