Merge pull request #4618 from aws-lumberyard-dev/Atom/EditorColorGrading
Implement LUT Generation Pass and hook up into Editor
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -105,6 +105,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LutGenerationPass",
|
||||
"TemplateName": "LutGenerationTemplate",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Name": "LookModificationTransformPass",
|
||||
"TemplateName": "LookModificationTransformTemplate",
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "LutGenerationTemplate",
|
||||
"PassClass": "LutGenerationPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "LutOutput",
|
||||
"SlotType": "Output",
|
||||
"ScopeAttachmentUsage": "RenderTarget",
|
||||
"LoadStoreAction": {
|
||||
"LoadAction": "DontCare"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ImageAttachments": [
|
||||
{
|
||||
"Name": "ColorGradingLut",
|
||||
"ImageDescriptor": {
|
||||
"Format": "R32G32B32A32_FLOAT",
|
||||
"BindFlags": [
|
||||
"ShaderWrite"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "LutOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "This",
|
||||
"Attachment": "ColorGradingLut"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "FullscreenTrianglePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/ColorGrading/LutGeneration.shader"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,7 +511,11 @@
|
||||
{
|
||||
"Name": "HDRColorGradingTemplate",
|
||||
"Path": "Passes/HDRColorGrading.pass"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "LutGenerationTemplate",
|
||||
"Path": "Passes/LutGeneration.pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ UNDISCLOSED.
|
||||
|
||||
#pragma once
|
||||
|
||||
static const float HALF_MAX = 65504.0f;
|
||||
#include <Atom/Features/PostProcessing/Aces.azsli>
|
||||
|
||||
float AcesCcToLinear(float value)
|
||||
{
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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 <Atom/RPI/Math.azsli>
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
#include <Atom/Features/PostProcessing/AcesColorSpaceConversion.azsli>
|
||||
#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);
|
||||
}
|
||||
|
||||
// perform color grading in ACEScg space
|
||||
float3 ColorGrade(float3 frameColor)
|
||||
{
|
||||
frameColor = lerp(frameColor, ColorGradePostExposure(frameColor, PassSrg::m_colorGradingExposure), PassSrg::m_colorAdjustmentWeight);
|
||||
frameColor = lerp(frameColor, ColorGradeKelvinColorTemp(frameColor, PassSrg::m_whiteBalanceKelvin), PassSrg::m_whiteBalanceWeight);
|
||||
frameColor = lerp(frameColor, ColorGradingContrast(frameColor, AcesCcMidGrey, PassSrg::m_colorGradingContrast), PassSrg::m_colorAdjustmentWeight);
|
||||
frameColor = lerp(frameColor, ColorGradeColorFilter(frameColor, PassSrg::m_colorFilterSwatch.rgb,
|
||||
PassSrg::m_colorFilterMultiply, PassSrg::m_colorFilterIntensity), PassSrg::m_colorAdjustmentWeight);
|
||||
frameColor = max(frameColor, 0.0);
|
||||
frameColor = lerp(frameColor, ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation), PassSrg::m_colorAdjustmentWeight);
|
||||
|
||||
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 = lerp(frameColor, ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation), PassSrg::m_finalAdjustmentWeight);
|
||||
frameColor = lerp(frameColor, ColorGradeHueShift(frameColor, PassSrg::m_colorGradingHueShift), PassSrg::m_finalAdjustmentWeight);
|
||||
return max(frameColor.rgb, 0.0);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 <Atom/RPI/Math.azsli>
|
||||
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
|
||||
|
||||
#include <Atom/Features/PostProcessing/Aces.azsli>
|
||||
#include <Atom/Features/PostProcessing/Shapers.azsli>
|
||||
|
||||
float3 convert2Dto3DLutCoords(float2 uv, float width, float height)
|
||||
{
|
||||
// convert from center pixel uvs to [0,1]
|
||||
float offset = 1.0/height/2.0;
|
||||
float scale = 1.0 - offset*2.0;
|
||||
|
||||
float2 adjustedUv = float2(uv.x * width, uv.y * height);
|
||||
float3 coords = float3(adjustedUv.x%height, 0.5 + int(adjustedUv.x/height), adjustedUv.y)/height;
|
||||
return (coords - offset)/scale;
|
||||
}
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
{
|
||||
// framebuffer sampler
|
||||
Sampler PointSampler
|
||||
{
|
||||
MinFilter = Point;
|
||||
MagFilter = Point;
|
||||
MipFilter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
int m_lutResolution;
|
||||
int m_shaperType;
|
||||
float m_shaperBias;
|
||||
float m_shaperScale;
|
||||
|
||||
float m_colorAdjustmentWeight;
|
||||
float m_colorGradingExposure;
|
||||
float m_colorGradingContrast;
|
||||
float m_colorGradingPreSaturation;
|
||||
float m_colorFilterIntensity;
|
||||
float m_colorFilterMultiply;
|
||||
float4 m_colorFilterSwatch;
|
||||
|
||||
float m_whiteBalanceWeight;
|
||||
float m_whiteBalanceKelvin;
|
||||
float m_whiteBalanceTint;
|
||||
|
||||
float m_splitToneBalance;
|
||||
float m_splitToneWeight;
|
||||
float4 m_splitToneShadowsColor;
|
||||
float4 m_splitToneHighlightsColor;
|
||||
|
||||
float m_smhShadowsStart;
|
||||
float m_smhShadowsEnd;
|
||||
float m_smhHighlightsStart;
|
||||
float m_smhHighlightsEnd;
|
||||
float m_smhWeight;
|
||||
float4 m_smhShadowsColor;
|
||||
float4 m_smhMidtonesColor;
|
||||
float4 m_smhHighlightsColor;
|
||||
|
||||
float3 m_channelMixingRed;
|
||||
float3 m_channelMixingGreen;
|
||||
float3 m_channelMixingBlue;
|
||||
|
||||
float m_finalAdjustmentWeight;
|
||||
float m_colorGradingPostSaturation;
|
||||
float m_colorGradingHueShift;
|
||||
}
|
||||
|
||||
#include <Atom/Features/PostProcessing/HDRColorGradingCommon.azsl>
|
||||
|
||||
struct PSOutput
|
||||
{
|
||||
float4 m_lutOutput : SV_Target0;
|
||||
};
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
ShaperType shaperType = (ShaperType)PassSrg::m_shaperType;
|
||||
int lutResolution = PassSrg::m_lutResolution;
|
||||
|
||||
PSOutput OUT;
|
||||
|
||||
// baseCoords are from 0-1
|
||||
float3 baseCoords = convert2Dto3DLutCoords(IN.m_texCoord, lutResolution*lutResolution, lutResolution);
|
||||
|
||||
float3 linearColor = ShaperToLinear(baseCoords, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale);
|
||||
|
||||
linearColor = TransformColor(linearColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg);
|
||||
float3 gradedColor = ColorGrade(linearColor);
|
||||
gradedColor = TransformColor(gradedColor, ColorSpaceId::ACEScg, ColorSpaceId::LinearSRGB);
|
||||
|
||||
// Bring back coordinates into 0-1
|
||||
float3 shapedColor = LinearToShaper(gradedColor, shaperType, PassSrg::m_shaperBias, PassSrg::m_shaperScale);
|
||||
shapedColor = saturate(shapedColor);
|
||||
|
||||
OUT.m_lutOutput = float4(shapedColor, 1.0);
|
||||
return OUT;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Source" : "LutGeneration",
|
||||
|
||||
"DepthStencilState" : {
|
||||
"Depth" : { "Enable" : false }
|
||||
},
|
||||
|
||||
"ProgramSettings":
|
||||
{
|
||||
"EntryPoints":
|
||||
[
|
||||
{
|
||||
"name": "MainVS",
|
||||
"type": "Vertex"
|
||||
},
|
||||
{
|
||||
"name": "MainPS",
|
||||
"type": "Fragment"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -13,18 +13,6 @@
|
||||
#include <Atom/Features/PostProcessing/FullscreenPixelInfo.azsli>
|
||||
#include <Atom/Features/PostProcessing/FullscreenVertex.azsli>
|
||||
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
#include <Atom/Features/PostProcessing/AcesColorSpaceConversion.azsli>
|
||||
#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;
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
{
|
||||
// get the framebuffer
|
||||
@@ -41,153 +29,42 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
float m_colorAdjustmentWeight;
|
||||
float m_colorGradingExposure;
|
||||
float m_colorGradingContrast;
|
||||
float m_colorGradingHueShift;
|
||||
float m_colorGradingPreSaturation;
|
||||
float m_colorFilterIntensity;
|
||||
float m_colorFilterMultiply;
|
||||
float4 m_colorFilterSwatch;
|
||||
|
||||
float m_whiteBalanceWeight;
|
||||
float m_whiteBalanceKelvin;
|
||||
float m_whiteBalanceTint;
|
||||
|
||||
float m_splitToneBalance;
|
||||
float m_splitToneWeight;
|
||||
float m_colorGradingPostSaturation;
|
||||
float4 m_splitToneShadowsColor;
|
||||
float4 m_splitToneHighlightsColor;
|
||||
|
||||
float m_smhShadowsStart;
|
||||
float m_smhShadowsEnd;
|
||||
float m_smhHighlightsStart;
|
||||
float m_smhHighlightsEnd;
|
||||
float m_smhWeight;
|
||||
float4 m_smhShadowsColor;
|
||||
float4 m_smhMidtonesColor;
|
||||
float4 m_smhHighlightsColor;
|
||||
|
||||
float3 m_channelMixingRed;
|
||||
float3 m_channelMixingGreen;
|
||||
float3 m_channelMixingBlue;
|
||||
|
||||
float4 m_colorFilterSwatch;
|
||||
float4 m_splitToneShadowsColor;
|
||||
float4 m_splitToneHighlightsColor;
|
||||
|
||||
float4 m_smhShadowsColor;
|
||||
float4 m_smhMidtonesColor;
|
||||
float4 m_smhHighlightsColor;
|
||||
float m_finalAdjustmentWeight;
|
||||
float m_colorGradingPostSaturation;
|
||||
float m_colorGradingHueShift;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
frameColor = max(frameColor, 0.0);
|
||||
frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation);
|
||||
frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneWeight);
|
||||
frameColor = ColorGradeChannelMixer(frameColor);
|
||||
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;
|
||||
}
|
||||
#include <Atom/Features/PostProcessing/HDRColorGradingCommon.azsl>
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,6 @@ set(FILES
|
||||
Passes/CascadedShadowmaps.pass
|
||||
Passes/CheckerboardResolveColor.pass
|
||||
Passes/CheckerboardResolveDepth.pass
|
||||
Passes/HDRColorGrading.pass
|
||||
Passes/ContrastAdaptiveSharpening.pass
|
||||
Passes/ConvertToAcescg.pass
|
||||
Passes/DebugOverlayParent.pass
|
||||
@@ -144,6 +143,7 @@ set(FILES
|
||||
Passes/ForwardSubsurfaceMSAA.pass
|
||||
Passes/FullscreenCopy.pass
|
||||
Passes/FullscreenOutputOnly.pass
|
||||
Passes/HDRColorGrading.pass
|
||||
Passes/ImGui.pass
|
||||
Passes/KawaseShadowBlur.pass
|
||||
Passes/LightAdaptationParent.pass
|
||||
@@ -158,6 +158,7 @@ set(FILES
|
||||
Passes/LowEndPipeline.pass
|
||||
Passes/LuminanceHeatmap.pass
|
||||
Passes/LuminanceHistogramGenerator.pass
|
||||
Passes/LutGeneration.pass
|
||||
Passes/MainPipeline.pass
|
||||
Passes/MainPipelineRenderToTexture.pass
|
||||
Passes/ThumbnailPipeline.pass
|
||||
@@ -281,6 +282,7 @@ set(FILES
|
||||
ShaderLib/Atom/Features/PostProcessing/FullscreenVertexUtil.azsli
|
||||
ShaderLib/Atom/Features/PostProcessing/GlyphData.azsli
|
||||
ShaderLib/Atom/Features/PostProcessing/GlyphRender.azsli
|
||||
ShaderLib/Atom/Features/PostProcessing/HDRColorGradingCommon.azsl
|
||||
ShaderLib/Atom/Features/PostProcessing/PostProcessUtil.azsli
|
||||
ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
|
||||
ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli
|
||||
@@ -315,6 +317,8 @@ set(FILES
|
||||
Shaders/BRDFTexture/BRDFTextureCS.shader
|
||||
Shaders/Checkerboard/CheckerboardColorResolveCS.azsl
|
||||
Shaders/Checkerboard/CheckerboardColorResolveCS.shader
|
||||
Shaders/ColorGrading/LutGeneration.azsl
|
||||
Shaders/ColorGrading/LutGeneration.shader
|
||||
Shaders/Depth/DepthPass.azsl
|
||||
Shaders/Depth/DepthPass.shader
|
||||
Shaders/Depth/DepthPassTransparentMax.shader
|
||||
|
||||
@@ -39,6 +39,7 @@ ly_add_target(
|
||||
Gem::Atom_Utils.Static
|
||||
Gem::Atom_Feature_Common.Public
|
||||
Gem::ImGui.imguilib
|
||||
3rdParty::TIFF
|
||||
#3rdParty::lux_core # AZ_TRAIT_LUXCORE_SUPPORTED is disabled in every platform, Issue #3915 will remove
|
||||
RUNTIME_DEPENDENCIES
|
||||
Gem::ImGui.imguilib
|
||||
@@ -75,6 +76,7 @@ ly_add_target(
|
||||
FILES_CMAKE
|
||||
atom_feature_common_shared_files.cmake
|
||||
../Assets/atom_feature_common_asset_files.cmake
|
||||
../Editor/atom_feature_common_editor_script_files.cmake
|
||||
PLATFORM_INCLUDE_FILES
|
||||
${pal_source_dir}/runtime_dependencies_clients.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
enum class LutResolution
|
||||
{
|
||||
Lut16x16x16 = 16,
|
||||
Lut32x32x32 = 32,
|
||||
Lut64x64x64 = 64
|
||||
};
|
||||
}
|
||||
}
|
||||
+25
-11
@@ -10,28 +10,42 @@
|
||||
// PARAM(NAME, MEMBER_NAME, DEFAULT_VALUE, ...)
|
||||
|
||||
AZ_GFX_BOOL_PARAM(Enabled, m_enabled, false)
|
||||
AZ_GFX_BOOL_PARAM(GenerateLut, m_generateLut, false)
|
||||
AZ_GFX_FLOAT_PARAM(ColorAdjustmentWeight, m_colorAdjustmentWeight, 1.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingExposure, m_colorGradingExposure, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingContrast, m_colorGradingContrast, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingHueShift, m_colorGradingHueShift, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingPreSaturation, m_colorGradingPreSaturation, 1.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingPreSaturation, m_colorGradingPreSaturation, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingFilterIntensity, m_colorGradingFilterIntensity, 1.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingFilterMultiply, m_colorGradingFilterMultiply, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingPostSaturation, m_colorGradingPostSaturation, 1.0)
|
||||
AZ_GFX_VEC3_PARAM(ColorFilterSwatch, m_colorFilterSwatch, AZ::Vector3(1.0f, 0.5f, 0.5f))
|
||||
|
||||
AZ_GFX_FLOAT_PARAM(WhiteBalanceWeight, m_whiteBalanceWeight, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(WhiteBalanceKelvin, m_whiteBalanceKelvin, 6600.0)
|
||||
AZ_GFX_FLOAT_PARAM(WhiteBalanceTint, m_whiteBalanceTint, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(SplitToneBalance, m_splitToneBalance, 0.0)
|
||||
|
||||
AZ_GFX_FLOAT_PARAM(SplitToneWeight, m_splitToneWeight, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(SplitToneBalance, m_splitToneBalance, 0.0)
|
||||
AZ_GFX_VEC3_PARAM(SplitToneShadowsColor, m_splitToneShadowsColor, AZ::Vector3(1.0f, 0.5f, 0.5f))
|
||||
AZ_GFX_VEC3_PARAM(SplitToneHighlightsColor, m_splitToneHighlightsColor, AZ::Vector3(0.1f, 1.0f, 0.1f))
|
||||
|
||||
AZ_GFX_FLOAT_PARAM(SmhWeight, m_smhWeight, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(SmhShadowsStart, m_smhShadowsStart, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(SmhShadowsEnd, m_smhShadowsEnd, 0.3)
|
||||
AZ_GFX_FLOAT_PARAM(SmhHighlightsStart, m_smhHighlightsStart, 0.55)
|
||||
AZ_GFX_FLOAT_PARAM(SmhHighlightsEnd, m_smhHighlightsEnd, 1.0)
|
||||
AZ_GFX_FLOAT_PARAM(SmhWeight, m_smhWeight, 0.0)
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingRed, m_channelMixingRed, AZ::Vector3(1.0f, 0.0f, 0.0f))
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingGreen, m_channelMixingGreen, AZ::Vector3(0.0f, 1.0f, 0.0f))
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingBlue, m_channelMixingBlue, AZ::Vector3(0.0f, 0.f, 1.0f))
|
||||
AZ_GFX_VEC3_PARAM(ColorFilterSwatch, m_colorFilterSwatch, AZ::Vector3(1.0f, 0.5f, 0.5f))
|
||||
AZ_GFX_VEC3_PARAM(SplitToneShadowsColor, m_splitToneShadowsColor, AZ::Vector3(1.0f, 0.5f, 0.5f))
|
||||
AZ_GFX_VEC3_PARAM(SplitToneHighlightsColor, m_splitToneHighlightsColor, AZ::Vector3(0.1f, 1.0f, 0.1f))
|
||||
AZ_GFX_VEC3_PARAM(SmhShadowsColor, m_smhShadowsColor, AZ::Vector3(1.0f, 0.25f, 0.25f))
|
||||
AZ_GFX_VEC3_PARAM(SmhMidtonesColor, m_smhMidtonesColor, AZ::Vector3(0.1f, 0.1f, 1.0f))
|
||||
AZ_GFX_VEC3_PARAM(SmhHighlightsColor, m_smhHighlightsColor, AZ::Vector3(1.0f, 0.0f, 1.0f))
|
||||
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingRed, m_channelMixingRed, AZ::Vector3(1.0f, 0.0f, 0.0f))
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingGreen, m_channelMixingGreen, AZ::Vector3(0.0f, 1.0f, 0.0f))
|
||||
AZ_GFX_VEC3_PARAM(ChannelMixingBlue, m_channelMixingBlue, AZ::Vector3(0.0f, 0.f, 1.0f))
|
||||
|
||||
AZ_GFX_COMMON_PARAM(AZ::Render::LutResolution, LutResolution, m_lutResolution, AZ::Render::LutResolution::Lut16x16x16)
|
||||
AZ_GFX_COMMON_PARAM(AZ::Render::ShaperPresetType, ShaperPresetType, m_shaperPresetType, AZ::Render::ShaperPresetType::None)
|
||||
AZ_GFX_COMMON_PARAM(float, CustomMinExposure, m_customMinExposure, -6.5)
|
||||
AZ_GFX_COMMON_PARAM(float, CustomMaxExposure, m_customMaxExposure, 6.5)
|
||||
|
||||
AZ_GFX_FLOAT_PARAM(FinalAdjustmentWeight, m_finalAdjustmentWeight, 1.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingPostSaturation, m_colorGradingPostSaturation, 0.0)
|
||||
AZ_GFX_FLOAT_PARAM(ColorGradingHueShift, m_colorGradingHueShift, 0.0)
|
||||
|
||||
+2
@@ -12,6 +12,8 @@
|
||||
#include <AzCore/Math/Vector4.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <Atom/Feature/ColorGrading/LutResolution.h>
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ColorGrading/LutGenerationPass.h>
|
||||
#include <Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h>
|
||||
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
|
||||
RPI::Ptr<LutGenerationPass> LutGenerationPass::Create(const RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
RPI::Ptr<LutGenerationPass> pass = aznew LutGenerationPass(descriptor);
|
||||
return AZStd::move(pass);
|
||||
}
|
||||
|
||||
LutGenerationPass::LutGenerationPass(const RPI::PassDescriptor& descriptor)
|
||||
: HDRColorGradingPass(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
void LutGenerationPass::InitializeInternal()
|
||||
{
|
||||
HDRColorGradingPass::InitializeInternal();
|
||||
|
||||
m_lutResolutionIndex.Reset();
|
||||
m_lutShaperTypeIndex.Reset();
|
||||
m_lutShaperScaleIndex.Reset();
|
||||
}
|
||||
|
||||
void LutGenerationPass::FrameBeginInternal(FramePrepareParams params)
|
||||
{
|
||||
const auto* colorGradingSettings = GetHDRColorGradingSettings();
|
||||
if (colorGradingSettings)
|
||||
{
|
||||
m_shaderResourceGroup->SetConstant(m_lutResolutionIndex, colorGradingSettings->GetLutResolution());
|
||||
|
||||
auto shaperParams = AcesDisplayMapperFeatureProcessor::GetShaperParameters(
|
||||
colorGradingSettings->GetShaperPresetType(),
|
||||
colorGradingSettings->GetCustomMinExposure(),
|
||||
colorGradingSettings->GetCustomMaxExposure());
|
||||
m_shaderResourceGroup->SetConstant(m_lutShaperTypeIndex, shaperParams.m_type);
|
||||
m_shaderResourceGroup->SetConstant(m_lutShaperBiasIndex, shaperParams.m_bias);
|
||||
m_shaderResourceGroup->SetConstant(m_lutShaperScaleIndex, shaperParams.m_scale);
|
||||
}
|
||||
|
||||
HDRColorGradingPass::FrameBeginInternal(params);
|
||||
}
|
||||
|
||||
void LutGenerationPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
|
||||
{
|
||||
const auto* colorGradingSettings = GetHDRColorGradingSettings();
|
||||
if (colorGradingSettings)
|
||||
{
|
||||
uint32_t lutResolution = aznumeric_cast<uint32_t>(colorGradingSettings->GetLutResolution());
|
||||
RHI::Size lutSize{ lutResolution * lutResolution, lutResolution, 1 };
|
||||
|
||||
RPI::Ptr<RPI::PassAttachment> attachment = FindOwnedAttachment(Name{ "ColorGradingLut" });
|
||||
RHI::ImageDescriptor& imageDescriptor = attachment->m_descriptor.m_image;
|
||||
imageDescriptor.m_size = lutSize;
|
||||
SetViewportScissorFromImageSize(lutSize);
|
||||
}
|
||||
HDRColorGradingPass::BuildCommandListInternal(context);
|
||||
}
|
||||
|
||||
bool LutGenerationPass::IsEnabled() const
|
||||
{
|
||||
const auto* colorGradingSettings = GetHDRColorGradingSettings();
|
||||
return colorGradingSettings ? colorGradingSettings->GetGenerateLut() : false;
|
||||
}
|
||||
|
||||
void LutGenerationPass::SetViewportScissorFromImageSize(const RHI::Size& imageSize)
|
||||
{
|
||||
const RHI::Viewport viewport(0.f, imageSize.m_width * 1.f, 0.f, imageSize.m_height * 1.f);
|
||||
const RHI::Scissor scissor(0, 0, imageSize.m_width, imageSize.m_height);
|
||||
m_viewportState = viewport;
|
||||
m_scissorState = scissor;
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 <PostProcessing/HDRColorGradingPass.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <Atom/RPI.Reflect/Shader/ShaderVariantKey.h>
|
||||
|
||||
#include <PostProcess/ColorGrading/HDRColorGradingSettings.h>
|
||||
#include <Atom/Feature/DisplayMapper/DisplayMapperFeatureProcessorInterface.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
// Performs color grading on an identity LUT strip
|
||||
class LutGenerationPass
|
||||
: public AZ::Render::HDRColorGradingPass
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LutGenerationPass, "{C21DABA8-B538-4C80-BA18-5B97CC9259E5}", AZ::RPI::FullscreenTrianglePass);
|
||||
AZ_CLASS_ALLOCATOR(LutGenerationPass, SystemAllocator, 0);
|
||||
|
||||
virtual ~LutGenerationPass() = default;
|
||||
|
||||
//! Creates a ColorGradingPass
|
||||
static RPI::Ptr<LutGenerationPass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
protected:
|
||||
LutGenerationPass(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
void InitializeInternal() override;
|
||||
void FrameBeginInternal(FramePrepareParams params) override;
|
||||
void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
|
||||
bool IsEnabled() const override;
|
||||
private:
|
||||
// Set viewport scissor based on output LUT resolution
|
||||
void SetViewportScissorFromImageSize(const RHI::Size& imageSize);
|
||||
|
||||
RHI::ShaderInputNameIndex m_lutResolutionIndex = "m_lutResolution";
|
||||
RHI::ShaderInputNameIndex m_lutShaperTypeIndex = "m_shaperType";
|
||||
RHI::ShaderInputNameIndex m_lutShaperBiasIndex = "m_shaperBias";
|
||||
RHI::ShaderInputNameIndex m_lutShaperScaleIndex = "m_shaperScale";
|
||||
};
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <Atom/Feature/AuxGeom/AuxGeomFeatureProcessor.h>
|
||||
#include <Atom/Feature/Utils/LightingPreset.h>
|
||||
#include <Atom/Feature/Utils/ModelPreset.h>
|
||||
#include <ColorGrading/LutGenerationPass.h>
|
||||
#include <PostProcess/PostProcessFeatureProcessor.h>
|
||||
#include <PostProcessing/BlendColorGradingLutsPass.h>
|
||||
#include <PostProcessing/BloomParentPass.h>
|
||||
@@ -230,6 +231,7 @@ namespace AZ
|
||||
passSystem->AddPassCreator(Name("HDRColorGradingPass"), &HDRColorGradingPass::Create);
|
||||
passSystem->AddPassCreator(Name("LookModificationCompositePass"), &LookModificationCompositePass::Create);
|
||||
passSystem->AddPassCreator(Name("LookModificationTransformPass"), &LookModificationPass::Create);
|
||||
passSystem->AddPassCreator(Name("LutGenerationPass"), &LutGenerationPass::Create);
|
||||
passSystem->AddPassCreator(Name("SMAAEdgeDetectionPass"), &SMAAEdgeDetectionPass::Create);
|
||||
passSystem->AddPassCreator(Name("SMAABlendingWeightCalculationPass"), &SMAABlendingWeightCalculationPass::Create);
|
||||
passSystem->AddPassCreator(Name("SMAANeighborhoodBlendingPass"), &SMAANeighborhoodBlendingPass::Create);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <AzCore/Preprocessor/EnumReflectUtils.h>
|
||||
#include <AzCore/Console/Console.h>
|
||||
|
||||
#include <tiffio.h>
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
@@ -110,6 +111,48 @@ namespace AZ
|
||||
return FrameCaptureOutputResult{FrameCaptureResult::InternalError, "Unable to save frame capture output to '" + outputFilePath + "'"};
|
||||
}
|
||||
|
||||
FrameCaptureOutputResult TiffFrameCaptureOutput(
|
||||
const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
AZStd::shared_ptr<AZStd::vector<uint8_t>> buffer = readbackResult.m_dataBuffer;
|
||||
const uint32_t width = readbackResult.m_imageDescriptor.m_size.m_width;
|
||||
const uint32_t height = readbackResult.m_imageDescriptor.m_size.m_height;
|
||||
const uint32_t numChannels = AZ::RHI::GetFormatComponentCount(readbackResult.m_imageDescriptor.m_format);
|
||||
const uint32_t bytesPerChannel = AZ::RHI::GetFormatSize(readbackResult.m_imageDescriptor.m_format) / numChannels;
|
||||
const uint32_t bitsPerChannel = bytesPerChannel * 8;
|
||||
|
||||
TIFF* out = TIFFOpen(outputFilePath.c_str(), "w");
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, numChannels);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitsPerChannel);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); // interpret each pixel as a float
|
||||
|
||||
size_t pitch = width * numChannels * bytesPerChannel;
|
||||
AZ_Assert((pitch * height) == buffer->size(), "Image buffer does not match allocated bytes for tiff saving.")
|
||||
unsigned char* raster = (unsigned char*)_TIFFmalloc((tsize_t)(pitch * height));
|
||||
memcpy(raster, buffer->data(), pitch * height);
|
||||
bool success = true;
|
||||
for (uint32_t h = 0; h < height; ++h)
|
||||
{
|
||||
size_t offset = h * pitch;
|
||||
int err = TIFFWriteScanline(out, raster + offset, h, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_TIFFfree(raster);
|
||||
TIFFClose(out);
|
||||
return success ? FrameCaptureOutputResult{ FrameCaptureResult::Success, AZStd::nullopt }
|
||||
: FrameCaptureOutputResult{ FrameCaptureResult::InternalError, "Unable to save tif frame capture output to " + outputFilePath };
|
||||
}
|
||||
|
||||
FrameCaptureOutputResult DdsFrameCaptureOutput(
|
||||
const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
@@ -492,6 +535,12 @@ namespace AZ
|
||||
m_result = ddsFrameCapture.m_result;
|
||||
m_latestCaptureInfo = ddsFrameCapture.m_errorMessage.value_or("");
|
||||
}
|
||||
else if (extension == "tiff" || extension == "tif")
|
||||
{
|
||||
const auto tifFrameCapture = TiffFrameCaptureOutput(m_outputFilePath, readbackResult);
|
||||
m_result = tifFrameCapture.m_result;
|
||||
m_latestCaptureInfo = tifFrameCapture.m_errorMessage.value_or("");
|
||||
}
|
||||
else if (extension == "png")
|
||||
{
|
||||
if (readbackResult.m_imageDescriptor.m_format == RHI::Format::R8G8B8A8_UNORM ||
|
||||
|
||||
+1
@@ -33,6 +33,7 @@ namespace AZ
|
||||
target->m_enabled = m_enabled;
|
||||
|
||||
#define AZ_GFX_BOOL_PARAM(NAME, MEMBER_NAME, DefaultValue) ;
|
||||
#define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) ;
|
||||
#define AZ_GFX_FLOAT_PARAM(NAME, MEMBER_NAME, DefaultValue) \
|
||||
{ \
|
||||
target->Set##NAME(AZ::Lerp(target->MEMBER_NAME, MEMBER_NAME, alpha)); \
|
||||
|
||||
+1
@@ -13,6 +13,7 @@
|
||||
#include <Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h>
|
||||
|
||||
#include <PostProcess/PostProcessBase.h>
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -32,33 +32,39 @@
|
||||
{
|
||||
FullscreenTrianglePass::InitializeInternal();
|
||||
|
||||
m_colorAdjustmentWeightIndex.Reset();
|
||||
m_colorGradingExposureIndex.Reset();
|
||||
m_colorGradingContrastIndex.Reset();
|
||||
m_colorGradingHueShiftIndex.Reset();
|
||||
m_colorGradingPreSaturationIndex.Reset();
|
||||
m_colorFilterIntensityIndex.Reset();
|
||||
m_colorFilterMultiplyIndex.Reset();
|
||||
m_colorFilterSwatchIndex.Reset();
|
||||
|
||||
m_whiteBalanceWeightIndex.Reset();
|
||||
m_whiteBalanceKelvinIndex.Reset();
|
||||
m_whiteBalanceTintIndex.Reset();
|
||||
|
||||
m_splitToneBalanceIndex.Reset();
|
||||
m_splitToneWeightIndex.Reset();
|
||||
m_colorGradingPostSaturationIndex.Reset();
|
||||
m_splitToneShadowsColorIndex.Reset();
|
||||
m_splitToneHighlightsColorIndex.Reset();
|
||||
|
||||
m_smhShadowsStartIndex.Reset();
|
||||
m_smhShadowsEndIndex.Reset();
|
||||
m_smhHighlightsStartIndex.Reset();
|
||||
m_smhHighlightsEndIndex.Reset();
|
||||
m_smhWeightIndex.Reset();
|
||||
m_smhShadowsColorIndex.Reset();
|
||||
m_smhMidtonesColorIndex.Reset();
|
||||
m_smhHighlightsColorIndex.Reset();
|
||||
|
||||
m_channelMixingRedIndex.Reset();
|
||||
m_channelMixingGreenIndex.Reset();
|
||||
m_channelMixingBlueIndex.Reset();
|
||||
|
||||
m_colorFilterSwatchIndex.Reset();
|
||||
m_splitToneShadowsColorIndex.Reset();
|
||||
m_splitToneHighlightsColorIndex.Reset();
|
||||
m_smhShadowsColorIndex.Reset();
|
||||
m_smhMidtonesColorIndex.Reset();
|
||||
m_smhHighlightsColorIndex.Reset();
|
||||
m_finalAdjustmentWeightIndex.Reset();
|
||||
m_colorGradingPostSaturationIndex.Reset();
|
||||
m_colorGradingHueShiftIndex.Reset();
|
||||
}
|
||||
|
||||
void HDRColorGradingPass::FrameBeginInternal(FramePrepareParams params)
|
||||
@@ -79,33 +85,39 @@
|
||||
const HDRColorGradingSettings* settings = GetHDRColorGradingSettings();
|
||||
if (settings)
|
||||
{
|
||||
m_shaderResourceGroup->SetConstant(m_colorAdjustmentWeightIndex, settings->GetColorAdjustmentWeight());
|
||||
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_colorFilterSwatchIndex, AZ::Vector4(settings->GetColorFilterSwatch()));
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_whiteBalanceWeightIndex, settings->GetWhiteBalanceWeight());
|
||||
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_splitToneShadowsColorIndex, AZ::Vector4(settings->GetSplitToneShadowsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_splitToneHighlightsColorIndex, AZ::Vector4(settings->GetSplitToneHighlightsColor()));
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_smhShadowsStartIndex, settings->GetSmhShadowsStart());
|
||||
m_shaderResourceGroup->SetConstant(m_smhShadowsEndIndex, settings->GetSmhShadowsEnd());
|
||||
m_shaderResourceGroup->SetConstant(m_smhHighlightsStartIndex, settings->GetSmhHighlightsStart());
|
||||
m_shaderResourceGroup->SetConstant(m_smhHighlightsEndIndex, settings->GetSmhHighlightsEnd());
|
||||
m_shaderResourceGroup->SetConstant(m_smhWeightIndex, settings->GetSmhWeight());
|
||||
m_shaderResourceGroup->SetConstant(m_smhShadowsColorIndex, AZ::Vector4(settings->GetSmhShadowsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_smhMidtonesColorIndex, AZ::Vector4(settings->GetSmhMidtonesColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_smhHighlightsColorIndex, AZ::Vector4(settings->GetSmhHighlightsColor()));
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_channelMixingRedIndex, settings->GetChannelMixingRed());
|
||||
m_shaderResourceGroup->SetConstant(m_channelMixingGreenIndex, settings->GetChannelMixingGreen());
|
||||
m_shaderResourceGroup->SetConstant(m_channelMixingBlueIndex, settings->GetChannelMixingBlue());
|
||||
|
||||
m_shaderResourceGroup->SetConstant(m_colorFilterSwatchIndex, AZ::Vector4(settings->GetColorFilterSwatch()));
|
||||
m_shaderResourceGroup->SetConstant(m_splitToneShadowsColorIndex, AZ::Vector4(settings->GetSplitToneShadowsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_splitToneHighlightsColorIndex, AZ::Vector4(settings->GetSplitToneHighlightsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_smhShadowsColorIndex, AZ::Vector4(settings->GetSmhShadowsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_smhMidtonesColorIndex, AZ::Vector4(settings->GetSmhMidtonesColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_smhHighlightsColorIndex, AZ::Vector4(settings->GetSmhHighlightsColor()));
|
||||
m_shaderResourceGroup->SetConstant(m_finalAdjustmentWeightIndex, settings->GetFinalAdjustmentWeight());
|
||||
m_shaderResourceGroup->SetConstant(m_colorGradingPostSaturationIndex, settings->GetColorGradingPostSaturation() * 0.01f + 1.0f);
|
||||
m_shaderResourceGroup->SetConstant(m_colorGradingHueShiftIndex, settings->GetColorGradingHueShift());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,37 +41,42 @@ namespace AZ
|
||||
void FrameBeginInternal(FramePrepareParams params) override;
|
||||
bool IsEnabled() const override;
|
||||
|
||||
private:
|
||||
const HDRColorGradingSettings* GetHDRColorGradingSettings() const;
|
||||
void SetSrgConstants();
|
||||
|
||||
virtual void SetSrgConstants();
|
||||
private:
|
||||
RHI::ShaderInputNameIndex m_colorAdjustmentWeightIndex = "m_colorAdjustmentWeight";
|
||||
RHI::ShaderInputNameIndex m_colorGradingExposureIndex = "m_colorGradingExposure";
|
||||
RHI::ShaderInputNameIndex m_colorGradingContrastIndex = "m_colorGradingContrast";
|
||||
RHI::ShaderInputNameIndex m_colorGradingHueShiftIndex = "m_colorGradingHueShift";
|
||||
RHI::ShaderInputNameIndex m_colorGradingPreSaturationIndex = "m_colorGradingPreSaturation";
|
||||
RHI::ShaderInputNameIndex m_colorFilterIntensityIndex = "m_colorFilterIntensity";
|
||||
RHI::ShaderInputNameIndex m_colorFilterMultiplyIndex = "m_colorFilterMultiply";
|
||||
RHI::ShaderInputNameIndex m_colorFilterSwatchIndex = "m_colorFilterSwatch";
|
||||
|
||||
RHI::ShaderInputNameIndex m_whiteBalanceWeightIndex = "m_whiteBalanceWeight";
|
||||
RHI::ShaderInputNameIndex m_whiteBalanceKelvinIndex = "m_whiteBalanceKelvin";
|
||||
RHI::ShaderInputNameIndex m_whiteBalanceTintIndex = "m_whiteBalanceTint";
|
||||
|
||||
RHI::ShaderInputNameIndex m_splitToneBalanceIndex = "m_splitToneBalance";
|
||||
RHI::ShaderInputNameIndex m_splitToneWeightIndex = "m_splitToneWeight";
|
||||
RHI::ShaderInputNameIndex m_colorGradingPostSaturationIndex = "m_colorGradingPostSaturation";
|
||||
RHI::ShaderInputNameIndex m_splitToneShadowsColorIndex = "m_splitToneShadowsColor";
|
||||
RHI::ShaderInputNameIndex m_splitToneHighlightsColorIndex = "m_splitToneHighlightsColor";
|
||||
|
||||
RHI::ShaderInputNameIndex m_smhShadowsStartIndex = "m_smhShadowsStart";
|
||||
RHI::ShaderInputNameIndex m_smhShadowsEndIndex = "m_smhShadowsEnd";
|
||||
RHI::ShaderInputNameIndex m_smhHighlightsStartIndex = "m_smhHighlightsStart";
|
||||
RHI::ShaderInputNameIndex m_smhHighlightsEndIndex = "m_smhHighlightsEnd";
|
||||
RHI::ShaderInputNameIndex m_smhWeightIndex = "m_smhWeight";
|
||||
RHI::ShaderInputNameIndex m_smhShadowsColorIndex = "m_smhShadowsColor";
|
||||
RHI::ShaderInputNameIndex m_smhMidtonesColorIndex = "m_smhMidtonesColor";
|
||||
RHI::ShaderInputNameIndex m_smhHighlightsColorIndex = "m_smhHighlightsColor";
|
||||
|
||||
RHI::ShaderInputNameIndex m_channelMixingRedIndex = "m_channelMixingRed";
|
||||
RHI::ShaderInputNameIndex m_channelMixingGreenIndex = "m_channelMixingGreen";
|
||||
RHI::ShaderInputNameIndex m_channelMixingBlueIndex = "m_channelMixingBlue";
|
||||
|
||||
RHI::ShaderInputNameIndex m_colorFilterSwatchIndex = "m_colorFilterSwatch";
|
||||
RHI::ShaderInputNameIndex m_splitToneShadowsColorIndex = "m_splitToneShadowsColor";
|
||||
RHI::ShaderInputNameIndex m_splitToneHighlightsColorIndex = "m_splitToneHighlightsColor";
|
||||
RHI::ShaderInputNameIndex m_smhShadowsColorIndex = "m_smhShadowsColor";
|
||||
RHI::ShaderInputNameIndex m_smhMidtonesColorIndex = "m_smhMidtonesColor";
|
||||
RHI::ShaderInputNameIndex m_smhHighlightsColorIndex = "m_smhHighlightsColor";
|
||||
RHI::ShaderInputNameIndex m_finalAdjustmentWeightIndex = "m_finalAdjustmentWeight";
|
||||
RHI::ShaderInputNameIndex m_colorGradingPostSaturationIndex = "m_colorGradingPostSaturation";
|
||||
RHI::ShaderInputNameIndex m_colorGradingHueShiftIndex = "m_colorGradingHueShift";
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -12,6 +12,7 @@ set(FILES
|
||||
Include/Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h
|
||||
Include/Atom/Feature/Automation/AtomAutomationBus.h
|
||||
Include/Atom/Feature/AuxGeom/AuxGeomFeatureProcessor.h
|
||||
Include/Atom/Feature/ColorGrading/LutResolution.h
|
||||
Include/Atom/Feature/CoreLights/CoreLightsConstants.h
|
||||
Include/Atom/Feature/DisplayMapper/AcesOutputTransformPass.h
|
||||
Include/Atom/Feature/DisplayMapper/AcesOutputTransformLutPass.h
|
||||
@@ -66,6 +67,8 @@ set(FILES
|
||||
Source/AuxGeom/DynamicPrimitiveProcessor.h
|
||||
Source/AuxGeom/FixedShapeProcessor.cpp
|
||||
Source/AuxGeom/FixedShapeProcessor.h
|
||||
Source/ColorGrading/LutGenerationPass.cpp
|
||||
Source/ColorGrading/LutGenerationPass.h
|
||||
Source/CoreLights/CapsuleLightFeatureProcessor.h
|
||||
Source/CoreLights/CapsuleLightFeatureProcessor.cpp
|
||||
Source/CoreLights/CascadedShadowmapsPass.h
|
||||
@@ -212,8 +215,6 @@ set(FILES
|
||||
Source/PostProcessing/BloomCompositePass.cpp
|
||||
Source/PostProcessing/BloomParentPass.h
|
||||
Source/PostProcessing/BloomParentPass.cpp
|
||||
Source/PostProcessing/HDRColorGradingPass.cpp
|
||||
Source/PostProcessing/HDRColorGradingPass.h
|
||||
Source/PostProcessing/DepthOfFieldCompositePass.h
|
||||
Source/PostProcessing/DepthOfFieldCompositePass.cpp
|
||||
Source/PostProcessing/DepthOfFieldBokehBlurPass.h
|
||||
@@ -234,6 +235,8 @@ set(FILES
|
||||
Source/PostProcessing/EyeAdaptationPass.h
|
||||
Source/PostProcessing/FastDepthAwareBlurPasses.cpp
|
||||
Source/PostProcessing/FastDepthAwareBlurPasses.h
|
||||
Source/PostProcessing/HDRColorGradingPass.cpp
|
||||
Source/PostProcessing/HDRColorGradingPass.h
|
||||
Source/PostProcessing/LookModificationCompositePass.cpp
|
||||
Source/PostProcessing/LookModificationCompositePass.h
|
||||
Source/PostProcessing/LookModificationTransformPass.cpp
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
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
|
||||
"""
|
||||
|
||||
"""
|
||||
This script is used by the Editor HDR Color Grading component to use a stored lut asset path
|
||||
and pass it onto a Look Modification Component.
|
||||
|
||||
The HDR Color Grading component will be disabled as it is not compatible with the Look
|
||||
Modification Component.
|
||||
"""
|
||||
import azlmbr
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
LOOK_MODIFICATION_LUT_PROPERTY_PATH = 'Controller|Configuration|Color Grading LUT'
|
||||
LOOK_MODIFICATION_ENABLE_PROPERTY_PATH = 'Controller|Configuration|Enable look modification'
|
||||
COLOR_GRADING_COMPONENT_ID = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDR Color Grading"], 0)
|
||||
LOOK_MODIFICATION_COMPONENT_ID = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Look Modification"], 0)
|
||||
|
||||
|
||||
def disable_hdr_color_grading_component(entity_id):
|
||||
componentOutcome = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'GetComponentOfType', entity_id, COLOR_GRADING_COMPONENT_ID[0])
|
||||
if(componentOutcome.IsSuccess()):
|
||||
azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'DisableComponents', [componentOutcome.GetValue()])
|
||||
|
||||
def add_look_modification_component(entity_id):
|
||||
componentOutcome = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'AddComponentsOfType', entity_id, LOOK_MODIFICATION_COMPONENT_ID)
|
||||
return componentOutcome.GetValue()[0]
|
||||
|
||||
def get_look_modification_component(entity_id):
|
||||
componentOutcome = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'GetComponentOfType', entity_id, LOOK_MODIFICATION_COMPONENT_ID[0])
|
||||
if componentOutcome.IsSuccess():
|
||||
return componentOutcome.GetValue()
|
||||
else:
|
||||
return None
|
||||
|
||||
def activate_look_modification_lut(look_modification_component, asset_relative_path):
|
||||
print(asset_relative_path)
|
||||
asset_id = azlmbr.asset.AssetCatalogRequestBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'GetAssetIdByPath',
|
||||
asset_relative_path,
|
||||
azlmbr.math.Uuid(),
|
||||
False
|
||||
)
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
look_modification_component,
|
||||
LOOK_MODIFICATION_LUT_PROPERTY_PATH,
|
||||
asset_id
|
||||
)
|
||||
azlmbr.editor.EditorComponentAPIBus(
|
||||
azlmbr.bus.Broadcast,
|
||||
'SetComponentProperty',
|
||||
look_modification_component,
|
||||
LOOK_MODIFICATION_ENABLE_PROPERTY_PATH,
|
||||
True
|
||||
)
|
||||
|
||||
def activate_lut_asset(entity_id, asset_relative_path):
|
||||
disable_hdr_color_grading_component(entity_id)
|
||||
|
||||
look_modification_component = get_look_modification_component(entity_id)
|
||||
if not look_modification_component:
|
||||
look_modification_component = add_look_modification_component(entity_id)
|
||||
|
||||
general.idle_wait_frames(5)
|
||||
|
||||
if look_modification_component:
|
||||
activate_look_modification_lut(look_modification_component, asset_relative_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser=argparse.ArgumentParser()
|
||||
parser.add_argument('--entityName', type=str, required=True, help='Entity ID to manage')
|
||||
parser.add_argument('--assetRelativePath', type=str, required=True, help='Lut asset relative path to activate')
|
||||
args=parser.parse_args()
|
||||
|
||||
# Get the entity id
|
||||
searchFilter = azlmbr.entity.SearchFilter()
|
||||
searchFilter.names = [args.entityName]
|
||||
entityIdList = azlmbr.entity.SearchBus(azlmbr.bus.Broadcast, 'SearchEntities', searchFilter)
|
||||
|
||||
for entityId in entityIdList:
|
||||
activate_lut_asset(entityId, args.assetRelativePath)
|
||||
@@ -0,0 +1,63 @@
|
||||
# coding:utf-8
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
import numpy as np
|
||||
import logging as _logging
|
||||
from ColorGrading import get_uv_coord
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
_MODULENAME = 'ColorGrading.azasset_converter_utils'
|
||||
|
||||
_LOGGER = _logging.getLogger(_MODULENAME)
|
||||
_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME}))
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
""" Utility functions for generating LUT azassets """
|
||||
def generate_lut_values(image_spec, image_buffer):
|
||||
lut_size = image_spec.height
|
||||
|
||||
lut_intervals = []
|
||||
lut_values = []
|
||||
|
||||
# First line contains the vertex intervals
|
||||
dv = 1023.0 / float(lut_size-1)
|
||||
for i in range(lut_size):
|
||||
lut_intervals.append(np.uint16(dv * i))
|
||||
# Texels are in R G B per line with indices increasing first with blue, then green, and then red.
|
||||
for r in range(lut_size):
|
||||
for g in range(lut_size):
|
||||
for b in range(lut_size):
|
||||
uv = get_uv_coord(lut_size, r, g, b)
|
||||
px = np.array(image_buffer.getpixel(uv[0], uv[1]), dtype='f')
|
||||
px = np.clip(px, 0.0, 1.0)
|
||||
px = np.uint16(px * 4095)
|
||||
lut_values.append(px)
|
||||
|
||||
return lut_intervals, lut_values
|
||||
|
||||
# To Do: add some input file validation
|
||||
# If the input file doesn't exist, you'll get a LUT with res of 0 x 0 and result in a math error
|
||||
#Resolution is 0 x 0
|
||||
#writing C:\Depot\o3de-engine\Gems\AtomLyIntegration\CommonFeatures\Tools\ColorGrading\TestData\Nuke\HDR\Nuke_Post_grade_LUT.3dl...
|
||||
#Traceback (most recent call last):
|
||||
#File "..\..\Editor\Scripts\ColorGrading\exr_to_3dl_azasset.py", line 103, in <module>
|
||||
#dv = 1023.0 / float(lutSize)
|
||||
# ZeroDivisionError: float division by zero
|
||||
|
||||
def write_3DL(file_path, lut_size, lut_intervals, lut_values):
|
||||
lut_file_path = f'{file_path}.3dl'
|
||||
_LOGGER.info(f"Writing {lut_file_path}...")
|
||||
lut_file = open(lut_file_path, 'w')
|
||||
for i in range(lut_size):
|
||||
lut_file.write(f"{lut_intervals[i]} ")
|
||||
lut_file.write("\n")
|
||||
for px in lut_values:
|
||||
lut_file.write(f"{px[0]} {px[1]} {px[2]}\n")
|
||||
lut_file.close()
|
||||
|
||||
@@ -46,48 +46,7 @@ from ColorGrading.from_3dl_to_azasset import write_azasset
|
||||
|
||||
from ColorGrading import get_uv_coord
|
||||
|
||||
def generate_lut_values(image_spec, image_buffer):
|
||||
lut_size = image_spec.height
|
||||
|
||||
lut_intervals = []
|
||||
lut_values = []
|
||||
|
||||
# First line contains the vertex intervals
|
||||
dv = 1023.0 / float(lut_size-1)
|
||||
for i in range(lut_size):
|
||||
lut_intervals.append(np.uint16(dv * i))
|
||||
# Texels are in R G B per line with indices increasing first with blue, then green, and then red.
|
||||
for r in range(lut_size):
|
||||
for g in range(lut_size):
|
||||
for b in range(lut_size):
|
||||
uv = get_uv_coord(lut_size, r, g, b)
|
||||
px = np.array(image_buffer.getpixel(uv[0], uv[1]), dtype='f')
|
||||
px = np.clip(px, 0.0, 1.0)
|
||||
px = np.uint16(px * 4095)
|
||||
lut_values.append(px)
|
||||
|
||||
return lut_intervals, lut_values
|
||||
|
||||
# To Do: add some input file validation
|
||||
# If the input file doesn't exist, you'll get a LUT with res of 0 x 0 and result in a math error
|
||||
#Resolution is 0 x 0
|
||||
#writing C:\Depot\o3de-engine\Gems\AtomLyIntegration\CommonFeatures\Tools\ColorGrading\TestData\Nuke\HDR\Nuke_Post_grade_LUT.3dl...
|
||||
#Traceback (most recent call last):
|
||||
#File "..\..\Editor\Scripts\ColorGrading\exr_to_3dl_azasset.py", line 103, in <module>
|
||||
#dv = 1023.0 / float(lutSize)
|
||||
# ZeroDivisionError: float division by zero
|
||||
|
||||
def write_3DL(file_path, lut_size, lut_intervals, lut_values):
|
||||
lut_file_path = f'{file_path}.3dl'
|
||||
_LOGGER.info(f"Writing {lut_file_path}...")
|
||||
lut_file = open(lut_file_path, 'w')
|
||||
for i in range(lut_size):
|
||||
lut_file.write(f"{lut_intervals[i]} ")
|
||||
lut_file.write("\n")
|
||||
for px in lut_values:
|
||||
lut_file.write(f"{px[0]} {px[1]} {px[2]}\n")
|
||||
lut_file.close()
|
||||
|
||||
from ColorGrading.azasset_converter_utils import generate_lut_values, write_3DL
|
||||
|
||||
###########################################################################
|
||||
# Main Code Block, runs this script as main (testing)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# coding:utf-8
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
"""
|
||||
input: a shaped .tiff representing a LUT (for instance coming out of photoshop)
|
||||
output: a inverse shaped LUT as .tiff
|
||||
^ as a .3DL (normalized lut file type)
|
||||
^ as a .azasset (for o3de engine)
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import math
|
||||
import site
|
||||
import pathlib
|
||||
from pathlib import Path
|
||||
import logging as _logging
|
||||
import numpy as np
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
_MODULENAME = 'ColorGrading.tiff_to_3dl_azasset'
|
||||
|
||||
_LOGGER = _logging.getLogger(_MODULENAME)
|
||||
_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME}))
|
||||
|
||||
import ColorGrading.initialize
|
||||
if ColorGrading.initialize.start():
|
||||
try:
|
||||
import OpenImageIO as oiio
|
||||
pass
|
||||
except ImportError as e:
|
||||
_LOGGER.error(f"invalid import: {e}")
|
||||
sys.exit(1)
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
from ColorGrading.from_3dl_to_azasset import write_azasset
|
||||
|
||||
from ColorGrading.azasset_converter_utils import generate_lut_values, write_3DL
|
||||
|
||||
###########################################################################
|
||||
# Main Code Block, runs this script as main (testing)
|
||||
# -------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
"""Run this file as main"""
|
||||
|
||||
parser=argparse.ArgumentParser()
|
||||
parser.add_argument('--i', type=str, required=True, help='input file')
|
||||
parser.add_argument('--o', type=str, required=True, help='output file')
|
||||
args=parser.parse_args()
|
||||
|
||||
# Read input image
|
||||
image_buffer=oiio.ImageBuf(args.i)
|
||||
image_spec=image_buffer.spec()
|
||||
|
||||
#img = oiio.ImageInput.open(args.i)
|
||||
#_LOGGER.info(f"Resolution is, x: {img.spec().width} and y: {img.spec().height}")
|
||||
|
||||
_LOGGER.info(f"Resolution is, x: {image_buffer.spec().width} and y: {image_buffer.spec().height}")
|
||||
|
||||
if image_spec.width != image_spec.height * image_spec.height:
|
||||
_LOGGER.info(f"invalid input file dimensions. Expect lengthwise LUT with dimension W: s*s X H: s, where s is the size of the LUT")
|
||||
sys.exit(1)
|
||||
|
||||
lut_intervals, lut_values = generate_lut_values(image_spec, image_buffer)
|
||||
|
||||
write_3DL(args.o, image_spec.height, lut_intervals, lut_values)
|
||||
|
||||
# write_azasset(file_path, lut_intervals, lut_values, azasset_json=AZASSET_LUT)
|
||||
write_azasset(args.o, lut_intervals, lut_values)
|
||||
|
||||
# example from command line
|
||||
# python % DCCSI_COLORGRADING_SCRIPTS %\lut_helper.py - -i C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.tiff - -op pre - grading - -shaper Log2 - 48nits - -o C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_32_LUT.exr
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Scripts/ColorGrading/__init__.py
|
||||
Scripts/ColorGrading/initialize.py
|
||||
Scripts/ColorGrading/azasset_converter_utils.py
|
||||
Scripts/ColorGrading/from_3dl_to_azasset.py
|
||||
Scripts/ColorGrading/tiff_to_3dl_azasset.py
|
||||
Scripts/ColorGrading/activate_lut_asset.py
|
||||
)
|
||||
+175
-15
@@ -7,6 +7,10 @@
|
||||
*/
|
||||
|
||||
#include <PostProcess/ColorGrading/EditorHDRColorGradingComponent.h>
|
||||
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntityObjectBus.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -18,7 +22,10 @@ namespace AZ
|
||||
|
||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<EditorHDRColorGradingComponent, BaseClass>()->Version(1);
|
||||
serializeContext->Class<EditorHDRColorGradingComponent, BaseClass>()
|
||||
->Version(2)
|
||||
->Field("generatedLut", &EditorHDRColorGradingComponent::m_generatedLutAbsolutePath)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
@@ -31,6 +38,20 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
|
||||
->Attribute(Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need to create page for PostProcessing.
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "LUT Generation")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->UIElement(AZ::Edit::UIHandlers::Button, "Generate LUT", "Generates a LUT from the scene's enabled color grading blend.")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
|
||||
->Attribute(AZ::Edit::Attributes::ButtonText, "Generate LUT")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorHDRColorGradingComponent::GenerateLut)
|
||||
->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorHDRColorGradingComponent::m_generatedLutAbsolutePath, "Generated LUT Path", "Generated LUT Path")
|
||||
->Attribute(AZ::Edit::Attributes::ReadOnly, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorHDRColorGradingComponent::GetGeneratedLutVisibilitySettings)
|
||||
->UIElement(AZ::Edit::UIHandlers::Button, "Activate LUT", "Use the generated LUT asset in a Look Modification component")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
|
||||
->Attribute(AZ::Edit::Attributes::ButtonText, "Activate LUT")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorHDRColorGradingComponent::ActivateLut)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorHDRColorGradingComponent::GetGeneratedLutVisibilitySettings)
|
||||
;
|
||||
|
||||
editContext->Class<HDRColorGradingComponentController>(
|
||||
@@ -47,6 +68,9 @@ namespace AZ
|
||||
"Enable HDR color grading.")
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Color Adjustment")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorAdjustmentWeight, "Weight", "Weight of color adjustments")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingExposure, "Exposure", "Exposure Value")
|
||||
->Attribute(Edit::Attributes::Min, AZStd::numeric_limits<float>::lowest())
|
||||
->Attribute(Edit::Attributes::Max, AZStd::numeric_limits<float>::max())
|
||||
@@ -66,10 +90,13 @@ namespace AZ
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingFilterMultiply, "Filter Multiply", "Filter Multiply Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_colorFilterSwatch, "Color Filter Swatch", "Color Filter Swatch Value")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_colorFilterSwatch, "Filter Swatch", "Color Filter Swatch Value")
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "White Balance")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_whiteBalanceWeight, "Weight", "Weight of white balance")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_whiteBalanceKelvin, "Temperature", "Temperature in Kelvin")
|
||||
->Attribute(Edit::Attributes::Min, 1000.0f)
|
||||
->Attribute(Edit::Attributes::Max, 40000.0f)
|
||||
@@ -79,14 +106,14 @@ namespace AZ
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Split Toning")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneWeight, "Split Tone Weight", "Modulates the split toning effect.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneWeight, "Weight", "Modulates the split toning effect.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneBalance, "Split Tone Balance", "Split Tone Balance Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneBalance, "Balance", "Split Tone Balance Value")
|
||||
->Attribute(Edit::Attributes::Min, -1.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneShadowsColor, "Split Tone Shadows Color", "Split Tone Shadows Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneHighlightsColor, "Split Tone Highlights Color", "Split Tone Highlights Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneShadowsColor, "Shadows Color", "Split Tone Shadows Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneHighlightsColor, "Highlights Color", "Split Tone Highlights Color")
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Channel Mixing")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
@@ -99,33 +126,52 @@ namespace AZ
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Shadow Midtones Highlights")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhWeight, "SMH Weight", "Modulates the SMH effect.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhWeight, "Weight", "Modulates the SMH effect.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsStart, "SMH Shadows Start", "SMH Shadows Start Value")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsStart, "Shadows Start", "SMH Shadows Start Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsEnd, "SMH Shadows End", "SMH Shadows End Value")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsEnd, "Shadows End", "SMH Shadows End Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsStart, "SMH Highlights Start", "SMH Highlights Start Value")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsStart, "Highlights Start", "SMH Highlights Start Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsEnd, "SMH Highlights End", "SMH Highlights End Value")
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsEnd, "Highlights End", "SMH Highlights End Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhShadowsColor, "SMH Shadows Color", "SMH Shadows Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhMidtonesColor, "SMH Midtones Color", "SMH Midtones Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhHighlightsColor, "SMH Highlights Color", "SMH Highlights Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhShadowsColor, "Shadows Color", "SMH Shadows Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhMidtonesColor, "Midtones Color", "SMH Midtones Color")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhHighlightsColor, "Highlights Color", "SMH Highlights Color")
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Final Adjustment")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_finalAdjustmentWeight, "Weight", "Weight of final adjustments")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingHueShift, "Hue Shift", "Hue Shift Value")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingPostSaturation, "Post Saturation", "Post Saturation Value")
|
||||
->Attribute(Edit::Attributes::Min, -100.0f)
|
||||
->Attribute(Edit::Attributes::Max, 100.0f)
|
||||
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "LUT Generation")
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &HDRColorGradingComponentConfig::m_lutResolution, "LUT Resolution", "Resolution of generated LUT")
|
||||
->EnumAttribute(LutResolution::Lut16x16x16, "16x16x16")
|
||||
->EnumAttribute(LutResolution::Lut32x32x32, "32x32x32")
|
||||
->EnumAttribute(LutResolution::Lut64x64x64, "64x64x64")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &HDRColorGradingComponentConfig::m_shaperPresetType,
|
||||
"Shaper Type", "Shaper Type.")
|
||||
->EnumAttribute(ShaperPresetType::None, "None")
|
||||
->EnumAttribute(ShaperPresetType::LinearCustomRange, "Linear Custom Range")
|
||||
->EnumAttribute(ShaperPresetType::Log2_48Nits, "Log2 48 nits")
|
||||
->EnumAttribute(ShaperPresetType::Log2_1000Nits, "Log2 1000 nits")
|
||||
->EnumAttribute(ShaperPresetType::Log2_2000Nits, "Log2 2000 nits")
|
||||
->EnumAttribute(ShaperPresetType::Log2_4000Nits, "Log2 4000 nits")
|
||||
->EnumAttribute(ShaperPresetType::Log2CustomRange, "Log2 Custom Range")
|
||||
->EnumAttribute(ShaperPresetType::PqSmpteSt2084, "PQ (SMPTE ST 2084)")
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -136,6 +182,120 @@ namespace AZ
|
||||
{
|
||||
}
|
||||
|
||||
void EditorHDRColorGradingComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
||||
{
|
||||
if (m_waitOneFrame)
|
||||
{
|
||||
m_waitOneFrame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const char* LutAttachment = "LutOutput";
|
||||
const AZStd::vector<AZStd::string> 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());
|
||||
|
||||
bool startedCapture = false;
|
||||
AZ::Render::FrameCaptureRequestBus::BroadcastResult(
|
||||
startedCapture,
|
||||
&AZ::Render::FrameCaptureRequestBus::Events::CapturePassAttachment,
|
||||
LutGenerationPassHierarchy,
|
||||
AZStd::string(LutAttachment),
|
||||
m_currentTiffFilePath,
|
||||
AZ::RPI::PassAttachmentReadbackOption::Output);
|
||||
|
||||
if (startedCapture)
|
||||
{
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorHDRColorGradingComponent::OnCaptureFinished([[maybe_unused]] AZ::Render::FrameCaptureResult result, [[maybe_unused]]const AZStd::string& info)
|
||||
{
|
||||
char resolvedInputFilePath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(m_currentTiffFilePath.c_str(), resolvedInputFilePath, AZ_MAX_PATH_LEN);
|
||||
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<AZStd::string_view> pythonArgs
|
||||
{
|
||||
"--i", resolvedInputFilePath,
|
||||
"--o", resolvedOutputFilePath
|
||||
};
|
||||
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs,
|
||||
TiffToAzassetPythonScriptPath,
|
||||
pythonArgs);
|
||||
|
||||
m_controller.m_configuration.m_generateLut = false;
|
||||
m_controller.OnConfigChanged();
|
||||
|
||||
m_generatedLutAbsolutePath = resolvedOutputFilePath + AZStd::string(".azasset");
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
|
||||
&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh,
|
||||
AzToolsFramework::PropertyModificationRefreshLevel::Refresh_EntireTree);
|
||||
|
||||
AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void EditorHDRColorGradingComponent::GenerateLut()
|
||||
{
|
||||
// turn on lut generation pass
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
m_currentTiffFilePath = AZStd::string::format(TempTiffFilePath, uuidString.c_str());
|
||||
m_currentLutFilePath = "@projectroot@/" + AZStd::string::format(GeneratedLutRelativePath, uuidString.c_str());
|
||||
|
||||
m_controller.SetGenerateLut(true);
|
||||
m_controller.OnConfigChanged();
|
||||
|
||||
m_waitOneFrame = true;
|
||||
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
AZ::u32 EditorHDRColorGradingComponent::ActivateLut()
|
||||
{
|
||||
using namespace AzFramework::StringFunc::Path;
|
||||
|
||||
AZStd::string entityName;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationRequests::GetEntityName, GetEntityId());
|
||||
|
||||
AZStd::string filename;
|
||||
GetFileName(m_generatedLutAbsolutePath.c_str(), filename);
|
||||
AZStd::string assetRelativePath = "LutGeneration/" + filename + ".azasset";
|
||||
AZStd::vector<AZStd::string_view> pythonArgs
|
||||
{
|
||||
"--entityName", entityName,
|
||||
"--assetRelativePath", assetRelativePath
|
||||
};
|
||||
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs,
|
||||
ActivateLutAssetPythonScriptPath,
|
||||
pythonArgs);
|
||||
|
||||
return AZ::Edit::PropertyRefreshLevels::EntireTree;
|
||||
}
|
||||
|
||||
bool EditorHDRColorGradingComponent::GetGeneratedLutVisibilitySettings()
|
||||
{
|
||||
return !m_generatedLutAbsolutePath.empty();
|
||||
}
|
||||
|
||||
u32 EditorHDRColorGradingComponent::OnConfigurationChanged()
|
||||
{
|
||||
m_controller.OnConfigChanged();
|
||||
|
||||
+26
@@ -8,16 +8,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentAdapter.h>
|
||||
#include <Atom/Feature/Utils/FrameCaptureBus.h>
|
||||
#include <PostProcess/ColorGrading/HDRColorGradingComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
static constexpr const char* const TempTiffFilePath{ "@usercache@/LutGeneration/SavedLut_%s.tiff" };
|
||||
static constexpr const char* const GeneratedLutRelativePath = { "LutGeneration/SavedLut_%s" };
|
||||
static constexpr const char* const TiffToAzassetPythonScriptPath{ "@engroot@/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/tiff_to_3dl_azasset.py" };
|
||||
static constexpr const char* const ActivateLutAssetPythonScriptPath{ "@engroot@/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/activate_lut_asset.py" };
|
||||
|
||||
class EditorHDRColorGradingComponent final
|
||||
: public AzToolsFramework::Components::
|
||||
EditorComponentAdapter<HDRColorGradingComponentController, HDRColorGradingComponent, HDRColorGradingComponentConfig>
|
||||
, private TickBus::Handler
|
||||
, private FrameCaptureNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
using BaseClass = AzToolsFramework::Components::EditorComponentAdapter<HDRColorGradingComponentController, HDRColorGradingComponent, HDRColorGradingComponentConfig>;
|
||||
@@ -30,6 +39,23 @@ namespace AZ
|
||||
|
||||
//! EditorRenderComponentAdapter overrides...
|
||||
AZ::u32 OnConfigurationChanged() override;
|
||||
|
||||
private:
|
||||
// AZ::TickBus overrides ...
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
// FrameCaptureNotificationBus overrides ...
|
||||
void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;
|
||||
|
||||
void GenerateLut();
|
||||
AZ::u32 ActivateLut();
|
||||
bool GetGeneratedLutVisibilitySettings();
|
||||
|
||||
bool m_waitOneFrame = false;
|
||||
AZStd::string m_currentTiffFilePath;
|
||||
AZStd::string m_currentLutFilePath;
|
||||
|
||||
AZStd::string m_generatedLutAbsolutePath;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+1
@@ -52,6 +52,7 @@ namespace AZ
|
||||
void HDRColorGradingComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC_CE("HDRColorGradingService"));
|
||||
incompatible.push_back(AZ_CRC_CE("LookModificationService"));
|
||||
}
|
||||
|
||||
void HDRColorGradingComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
+2
-2
@@ -49,12 +49,12 @@ namespace AZ
|
||||
|
||||
void LookModificationComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("LookModificationService", 0x207b7539));
|
||||
provided.push_back(AZ_CRC_CE("LookModificationService"));
|
||||
}
|
||||
|
||||
void LookModificationComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("LookModificationService", 0x207b7539));
|
||||
incompatible.push_back(AZ_CRC("LookModificationService"));
|
||||
}
|
||||
|
||||
void LookModificationComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
Reference in New Issue
Block a user