Implement lut resolution.
Signed-off-by: rbarrand <rbarrand@amazon.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
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):
|
||||
typeIdsList = azlmbr.editor.EditorComponentAPIBus(azlmbr.bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["HDR Color Grading"], 0)
|
||||
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()
|
||||
|
||||
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)
|
||||
@@ -28,19 +28,39 @@ static const float FloatMax = FLOAT_32_MAX; // Max float number representable
|
||||
|
||||
static const float AcesCcMidGrey = 0.4135884;
|
||||
|
||||
float3 convert2Dto3DLutCoords(float2 uv)
|
||||
float3 convert2Dto3DLutCoords(float2 uv, float width, float height)
|
||||
{
|
||||
const float height = 16.0;
|
||||
const float width = 256.0;
|
||||
//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 * width, uv.y * height);
|
||||
float3 coords = float3(adjustedUv.x%height, adjustedUv.x/height, adjustedUv.y);
|
||||
float2 adjustedUv = float2(uv.x * height*height, uv.y * height);
|
||||
float3 coords = float3(adjustedUv.x%height, uv.x*height, adjustedUv.y);
|
||||
return coords/height;
|
||||
//return float3(uv.x, uv.x, uv.y);
|
||||
}
|
||||
|
||||
enum class LutResolution
|
||||
{
|
||||
Lut16x16x16,
|
||||
Lut32x32x32,
|
||||
Lut64x64x64
|
||||
};
|
||||
|
||||
ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
{
|
||||
// framebuffer sampler
|
||||
Sampler PointSampler
|
||||
{
|
||||
MinFilter = Point;
|
||||
MagFilter = Point;
|
||||
MipFilter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
Sampler LinearSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
@@ -53,6 +73,13 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback
|
||||
|
||||
// Identity LUTs
|
||||
Texture3D<float4> m_identityLut16x16x16;
|
||||
Texture3D<float4> m_identityLut32x32x32;
|
||||
Texture3D<float4> m_identityLut64x64x64;
|
||||
|
||||
int m_lutResolution;
|
||||
int m_shaperType;
|
||||
float m_shaperBias;
|
||||
float m_shaperScale;
|
||||
|
||||
float m_colorGradingExposure;
|
||||
float m_colorGradingContrast;
|
||||
@@ -125,7 +152,8 @@ float3 ColorGradeHueShift (float3 frameColor, float amount)
|
||||
|
||||
float3 ColorGradeSaturation (float3 frameColor, float control)
|
||||
{
|
||||
const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg);
|
||||
const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::LinearSRGB);
|
||||
//const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg);
|
||||
return (frameColor - vLuminance) * control + vLuminance;
|
||||
}
|
||||
|
||||
@@ -184,20 +212,7 @@ float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStar
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -207,6 +222,11 @@ struct PSOutput
|
||||
float4 m_lutOutput : SV_Target0;
|
||||
};
|
||||
|
||||
float3 InverseGamma(float3 color)
|
||||
{
|
||||
return pow(color, 2.2);
|
||||
}
|
||||
|
||||
float3 GetSourceLutLinearColor(float3 baseColor, Texture3D<float4> sourceLut, ShaperType shaperType, float shaperBias, float shaperScale)
|
||||
{
|
||||
// Convert from reference linearColor to the lutCoordinate for this Lut
|
||||
@@ -219,38 +239,49 @@ float3 GetSourceLutLinearColor(float3 baseColor, Texture3D<float4> sourceLut, Sh
|
||||
float3 coordScale = (outputDimensions - 1.0) / outputDimensions;
|
||||
lutCoord = (lutCoord * coordScale) + coordBias;
|
||||
|
||||
float3 lutColor = sourceLut.SampleLevel(PassSrg::LinearSampler, lutCoord, 0).rgb;
|
||||
float3 lutColor = sourceLut.SampleLevel(PassSrg::PointSampler, lutCoord, 0).rgb;
|
||||
// Convert to linear
|
||||
float3 linearColor = ShaperToLinear(lutColor, shaperType, shaperBias, shaperScale);
|
||||
return linearColor;
|
||||
}
|
||||
|
||||
float3 InverseGamma(float3 color)
|
||||
{
|
||||
return pow(color, 2.2);
|
||||
}
|
||||
|
||||
PSOutput MainPS(VSOutput IN)
|
||||
{
|
||||
int shaperNum = 0;
|
||||
ShaperType shaperType = (ShaperType)shaperNum;
|
||||
//ShaperType shaperType = ShaperType::ShaperLinear;
|
||||
float bias = 0.0;
|
||||
float scale = 1.0;
|
||||
ShaperType shaperType = (ShaperType)PassSrg::m_shaperType;
|
||||
|
||||
PSOutput OUT;
|
||||
|
||||
float3 baseCoords = convert2Dto3DLutCoords(IN.m_texCoord);
|
||||
float3 baseColor = ShaperToLinear(baseCoords, shaperType, bias, scale);
|
||||
|
||||
float3 lutColor = PassSrg::m_identityLut16x16x16.Sample(PassSrg::LinearSampler, baseColor, 0.0).rgb;
|
||||
//float3 lutColor = GetSourceLutLinearColor(baseColor, PassSrg::m_identityLut16x16x16, shaperType, bias, scale);
|
||||
|
||||
//float3 gradedColor = float4(ColorGrade(lutColor), 1.0);
|
||||
|
||||
//float3 finalColor = LinearToShaper(gradedColor, shaperType, bias, scale);
|
||||
|
||||
OUT.m_lutOutput = float4(lutColor, 1.0);
|
||||
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;
|
||||
switch(lutRes)
|
||||
{
|
||||
case LutResolution::Lut16x16x16:
|
||||
{
|
||||
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:
|
||||
{
|
||||
baseCoords = convert2Dto3DLutCoords(IN.m_texCoord, 1024, 32);
|
||||
lutColor = PassSrg::m_identityLut32x32x32.Sample(PassSrg::PointSampler, baseCoords, 0.0).rgb;
|
||||
break;
|
||||
}
|
||||
case LutResolution::Lut64x64x64:
|
||||
{
|
||||
baseCoords = convert2Dto3DLutCoords(IN.m_texCoord, 4096, 64);
|
||||
lutColor = PassSrg::m_identityLut64x64x64.Sample(PassSrg::PointSampler, baseCoords, 0.0).rgb;
|
||||
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);
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
Lut32x32x32,
|
||||
Lut64x64x64
|
||||
};
|
||||
}
|
||||
}
|
||||
+4
@@ -36,3 +36,7 @@ AZ_GFX_VEC3_PARAM(SplitToneHighlightsColor, m_splitToneHighlightsColor, AZ::Vect
|
||||
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_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)
|
||||
|
||||
+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
|
||||
{
|
||||
|
||||
@@ -38,22 +38,19 @@ namespace AZ
|
||||
AcesDisplayMapperFeatureProcessor* dmfp = scene->GetFeatureProcessor<AcesDisplayMapperFeatureProcessor>();
|
||||
if (dmfp)
|
||||
{
|
||||
// load the image assets
|
||||
auto assetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(
|
||||
"lookuptables/lut_identitylinear_16x16x16.azasset", AZ::RPI::AssetUtils::TraceLevel::Error);
|
||||
AZ_Assert(assetId.IsValid(), "LUT Asset is not valid.");
|
||||
dmfp->GetLutFromAssetId(m_colorGradingLut, assetId);
|
||||
for (int i = 0; i < NumLuts; ++i)
|
||||
{
|
||||
auto assetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath(LutIdentityProductPath[i], AZ::RPI::AssetUtils::TraceLevel::Error);
|
||||
AZ_Assert(assetId.IsValid(), "LUT Asset is not valid.");
|
||||
dmfp->GetLutFromAssetId(m_colorGradingLuts[i], assetId);
|
||||
|
||||
// set srg image index
|
||||
m_shaderResourceGroup->SetImageView(m_identityLut16x16x16Index, m_colorGradingLut.m_lutStreamingImage->GetImageView());
|
||||
m_shaderResourceGroup->SetImageView(m_identityLutIndices[i], m_colorGradingLuts[i].m_lutStreamingImage->GetImageView());
|
||||
|
||||
// Get the output image attachment
|
||||
RPI::Ptr<RPI::PassAttachment> attachment = FindOwnedAttachment(Name{ "ColorGradingLut" });
|
||||
RHI::ImageDescriptor& imageDescriptor = attachment->m_descriptor.m_image;
|
||||
imageDescriptor.m_size = RHI::Size(
|
||||
m_colorGradingLut.m_lutStreamingImage->GetDescriptor().m_size.m_width*m_colorGradingLut.m_lutStreamingImage->GetDescriptor().m_size.m_width,
|
||||
m_colorGradingLut.m_lutStreamingImage->GetDescriptor().m_size.m_height,
|
||||
1);
|
||||
m_colorGradingLutSizes[i] = RHI::Size(
|
||||
m_colorGradingLuts[i].m_lutStreamingImage->GetDescriptor().m_size.m_width * m_colorGradingLuts[i].m_lutStreamingImage->GetDescriptor().m_size.m_width,
|
||||
m_colorGradingLuts[i].m_lutStreamingImage->GetDescriptor().m_size.m_height,
|
||||
1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,27 +61,46 @@ namespace AZ
|
||||
{
|
||||
HDRColorGradingPass::InitializeInternal();
|
||||
|
||||
m_identityLut16x16x16Index.Reset();
|
||||
m_identityLut32x32x32Index.Reset();
|
||||
m_identityLut64x64x64Index.Reset();
|
||||
|
||||
//// load the image assets
|
||||
//DisplayMapperAssetLut m_colorGradingLut;
|
||||
//auto assetId = AZ::RPI::AssetUtils::GetAssetIdForProductPath("lookuptables/lut_identitylinear_16x16x16.azasset", AZ::RPI::AssetUtils::TraceLevel::Error);
|
||||
//AcesDisplayMapperFeatureProcessor* dmfp = GetScene()->GetFeatureProcessor<AcesDisplayMapperFeatureProcessor>();
|
||||
//dmfp->GetLutFromAssetId(m_colorGradingLut, assetId);
|
||||
|
||||
//// set srg image index
|
||||
//m_shaderResourceGroup->SetImageView(m_identityLut16x16x16Index, m_colorGradingLut.m_lutStreamingImage->GetImageView());
|
||||
for (int i = 0; i < NumLuts; ++i)
|
||||
{
|
||||
m_identityLutIndices[i].Reset();
|
||||
}
|
||||
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)
|
||||
{
|
||||
LutResolution lutResolution = colorGradingSettings->GetLutResolution();
|
||||
|
||||
RPI::Ptr<RPI::PassAttachment> attachment = FindOwnedAttachment(Name{ "ColorGradingLut" });
|
||||
RHI::ImageDescriptor& imageDescriptor = attachment->m_descriptor.m_image;
|
||||
imageDescriptor.m_size = m_colorGradingLutSizes[(int)lutResolution];
|
||||
SetViewportScissorFromImageSize(m_colorGradingLutSizes[(int)lutResolution]);
|
||||
}
|
||||
HDRColorGradingPass::BuildCommandListInternal(context);
|
||||
}
|
||||
|
||||
@@ -94,6 +110,15 @@ namespace AZ
|
||||
//return colorGradingSettings ? colorGradingSettings->GetGenerateLut() : false;
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace AZ
|
||||
: public AZ::Render::HDRColorGradingPass
|
||||
{
|
||||
public:
|
||||
static const int NumLuts = 3;
|
||||
|
||||
AZ_RTTI(LutGenerationPass, "{C21DABA8-B538-4C80-BA18-5B97CC9259E5}", AZ::RPI::FullscreenTrianglePass);
|
||||
AZ_CLASS_ALLOCATOR(LutGenerationPass, SystemAllocator, 0);
|
||||
|
||||
@@ -41,11 +43,25 @@ namespace AZ
|
||||
void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
|
||||
bool IsEnabled() const override;
|
||||
private:
|
||||
RHI::ShaderInputNameIndex m_identityLut16x16x16Index = "m_identityLut16x16x16";
|
||||
RHI::ShaderInputNameIndex m_identityLut32x32x32Index = "m_identityLut32x32x32";
|
||||
RHI::ShaderInputNameIndex m_identityLut64x64x64Index = "m_identityLut64x64x64";
|
||||
// Set viewport scissor based on output LUT resolution
|
||||
void SetViewportScissorFromImageSize(const RHI::Size& imageSize);
|
||||
|
||||
DisplayMapperAssetLut m_colorGradingLut;
|
||||
DisplayMapperAssetLut m_colorGradingLuts[NumLuts];
|
||||
RHI::Size m_colorGradingLutSizes[NumLuts];
|
||||
|
||||
const char* const LutIdentityProductPath[NumLuts] = {
|
||||
"lookuptables/lut_identitylinear_16x16x16.azasset",
|
||||
"lookuptables/lut_identitylinear_32x32x32.azasset",
|
||||
"lookuptables/lut_identitylinear_64x64x64.azasset" };
|
||||
|
||||
RHI::ShaderInputNameIndex m_identityLutIndices[NumLuts] = {
|
||||
"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;
|
||||
};
|
||||
|
||||
+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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# 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 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()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# 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
|
||||
+78
-5
@@ -8,6 +8,9 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@@ -19,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())
|
||||
{
|
||||
@@ -38,6 +44,14 @@ namespace AZ
|
||||
->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>(
|
||||
@@ -133,6 +147,22 @@ namespace AZ
|
||||
->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)")
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -163,7 +193,8 @@ namespace AZ
|
||||
startedCapture,
|
||||
&AZ::Render::FrameCaptureRequestBus::Events::CapturePassAttachment,
|
||||
LutGenerationPassHierarchy,
|
||||
AZStd::string(LutAttachment), TempTiffFilePath,
|
||||
AZStd::string(LutAttachment),
|
||||
m_currentTiffFilePath,
|
||||
AZ::RPI::PassAttachmentReadbackOption::Output);
|
||||
|
||||
m_lutGenerationInProgress = !startedCapture;
|
||||
@@ -173,9 +204,9 @@ namespace AZ
|
||||
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(TempTiffFilePath, resolvedInputFilePath, AZ_MAX_PATH_LEN);
|
||||
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(GeneratedLutFilePath, resolvedOutputFilePath, AZ_MAX_PATH_LEN);
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(m_currentLutFilePath.c_str(), resolvedOutputFilePath, AZ_MAX_PATH_LEN);
|
||||
|
||||
AZStd::vector<AZStd::string_view> pythonArgs
|
||||
{
|
||||
@@ -185,11 +216,17 @@ namespace AZ
|
||||
|
||||
AzToolsFramework::EditorPythonRunnerRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPythonRunnerRequestBus::Events::ExecuteByFilenameWithArgs,
|
||||
"@devroot@/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/tiff_to_3dl_azasset.py", pythonArgs);
|
||||
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::TickBus::Handler::BusDisconnect();
|
||||
AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
@@ -197,6 +234,13 @@ namespace AZ
|
||||
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 = "@devassets@/" + AZStd::string::format(GeneratedLutRelativePath, uuidString.c_str());
|
||||
|
||||
m_lutGenerationInProgress = true;
|
||||
m_controller.m_configuration.m_generateLut = true;
|
||||
m_controller.OnConfigChanged();
|
||||
@@ -206,6 +250,35 @@ namespace AZ
|
||||
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();
|
||||
|
||||
+10
-2
@@ -17,8 +17,10 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
static const char* const TempTiffFilePath{ "@projectcache@/LutGeneration/SavedLut.tiff" };
|
||||
static const char* const GeneratedLutFilePath{ "@projectcache@/LutGeneration/SavedLut" };
|
||||
static const char* const TempTiffFilePath{ "@projectcache@/LutGeneration/SavedLut_%s.tiff" };
|
||||
static const char* const GeneratedLutRelativePath = { "LutGeneration/SavedLut_%s" };
|
||||
static const char* const TiffToAzassetPythonScriptPath{ "@devroot@/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/tiff_to_3dl_azasset.py" };
|
||||
static const char* const ActivateLutAssetPythonScriptPath{ "@devroot@/Gems/Atom/Feature/Common/Assets/Scripts/activate_lut_asset.py" };
|
||||
|
||||
class EditorHDRColorGradingComponent final
|
||||
: public AzToolsFramework::Components::
|
||||
@@ -50,9 +52,15 @@ namespace AZ
|
||||
void OnCaptureFinished(AZ::Render::FrameCaptureResult result, const AZStd::string& info) override;
|
||||
|
||||
void GenerateLut();
|
||||
AZ::u32 ActivateLut();
|
||||
bool GetGeneratedLutVisibilitySettings();
|
||||
|
||||
AZStd::atomic_bool m_lutGenerationInProgress = false;
|
||||
int m_frameCounter;
|
||||
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("LookModificationService", 0x207b7539));
|
||||
}
|
||||
|
||||
void HDRColorGradingComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
|
||||
Reference in New Issue
Block a user