ATOM-15086 Image Pipeline Unexpectedly Pre-Multiplying Alpha into Color Channels (#5358)
Applied the discard alpha in the begining of converting. Also deleted some unused processing settings and steps. Signed-off-by: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com>
This commit is contained in:
@@ -46,7 +46,6 @@ namespace ImageProcessingAtom
|
||||
enum ConvertStep
|
||||
{
|
||||
StepValidateInput = 0,
|
||||
StepGenerateColorChart,
|
||||
StepConvertToLinear,
|
||||
StepSwizzle,
|
||||
StepCubemapLayout,
|
||||
@@ -55,9 +54,7 @@ namespace ImageProcessingAtom
|
||||
StepMipmap,
|
||||
StepGlossFromNormal,
|
||||
StepPostNormalize,
|
||||
StepCreateHighPass,
|
||||
StepConvertOutputColorSpace,
|
||||
StepAlphaImage,
|
||||
StepConvertPixelFormat,
|
||||
StepSaveToFile,
|
||||
StepAll
|
||||
@@ -66,7 +63,6 @@ namespace ImageProcessingAtom
|
||||
[[maybe_unused]] const char ProcessStepNames[StepAll][64] =
|
||||
{
|
||||
"ValidateInput",
|
||||
"GenerateColorChart",
|
||||
"ConvertToLinear",
|
||||
"Swizzle",
|
||||
"CubemapLayout",
|
||||
@@ -75,9 +71,7 @@ namespace ImageProcessingAtom
|
||||
"Mipmap",
|
||||
"GlossFromNormal",
|
||||
"PostNormalize",
|
||||
"CreateHighPass",
|
||||
"ConvertOutputColorSpace",
|
||||
"AlphaImage",
|
||||
"ConvertPixelFormat",
|
||||
"SaveToFile",
|
||||
};
|
||||
@@ -94,11 +88,6 @@ namespace ImageProcessingAtom
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IImageObjectPtr ImageConvertProcess::GetOutputAlphaImage()
|
||||
{
|
||||
return m_alphaImage;
|
||||
}
|
||||
|
||||
IImageObjectPtr ImageConvertProcess::GetOutputIBLSpecularCubemap()
|
||||
{
|
||||
return m_iblSpecularCubemapImage;
|
||||
@@ -180,6 +169,58 @@ namespace ImageProcessingAtom
|
||||
m_image = new ImageToProcess(IImageObjectPtr(m_input->m_inputImage->Clone(mipsToClone)));
|
||||
}
|
||||
|
||||
break;
|
||||
case StepConvertToLinear:
|
||||
// convert to linear space and the output image pixel format should be rgba32f
|
||||
ConvertToLinear();
|
||||
break;
|
||||
case StepSwizzle:
|
||||
{
|
||||
// swizzle if swizzle was set or decard alpha
|
||||
bool swizzleWasSet = m_input->m_presetSetting.m_swizzle.size() >= 4;
|
||||
if (swizzleWasSet || m_input->m_presetSetting.m_discardAlpha)
|
||||
{
|
||||
AZStd::string swizzle = "rgba";
|
||||
if (swizzleWasSet)
|
||||
{
|
||||
swizzle = m_input->m_presetSetting.m_swizzle.substr(0, 4);
|
||||
}
|
||||
|
||||
if (m_input->m_presetSetting.m_discardAlpha)
|
||||
{
|
||||
swizzle[3] = '1';
|
||||
}
|
||||
|
||||
m_image->Get()->Swizzle(swizzle.c_str());
|
||||
if (!m_input->m_presetSetting.m_discardAlpha)
|
||||
{
|
||||
m_alphaContent = EAlphaContent::eAlphaContent_Absent;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_alphaContent = m_image->Get()->GetAlphaContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StepCubemapLayout:
|
||||
// convert cubemap image's layout to vertical strip used in game.
|
||||
if (IsConvertToCubemap())
|
||||
{
|
||||
if (!m_image->ConvertCubemapLayout(CubemapLayoutVertical))
|
||||
{
|
||||
m_image->Set(nullptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StepPreNormalize:
|
||||
// normalize base image before mipmap generation if glossfromnormals is enabled and require normalize
|
||||
if (m_input->m_presetSetting.m_isMipRenormalize && m_input->m_presetSetting.m_glossFromNormals)
|
||||
{
|
||||
// Normalize the base mip map. This has to be done explicitly because we need to disable mip renormalization to
|
||||
// preserve the normal length when deriving the normal variance
|
||||
m_image->Get()->NormalizeVectors(0, 1);
|
||||
}
|
||||
break;
|
||||
case StepGenerateIBL:
|
||||
if (IsConvertToCubemap())
|
||||
@@ -204,56 +245,6 @@ namespace ImageProcessingAtom
|
||||
m_isFinished = true;
|
||||
}
|
||||
break;
|
||||
case StepGenerateColorChart:
|
||||
// GenerateColorChart.
|
||||
if (m_input->m_presetSetting.m_isColorChart)
|
||||
{
|
||||
// Convert to uncompressed format if it's compressed format. For example, loaded from DDS file.
|
||||
if (!CPixelFormats::GetInstance().IsPixelFormatUncompressed(m_image->Get()->GetPixelFormat()))
|
||||
{
|
||||
m_image->ConvertFormat(ePixelFormat_R32G32B32A32F);
|
||||
}
|
||||
|
||||
m_image->CreateColorChart();
|
||||
}
|
||||
break;
|
||||
case StepConvertToLinear:
|
||||
// convert to linear space and the output image pixel format should be rgba32f
|
||||
ConvertToLinear();
|
||||
break;
|
||||
case StepSwizzle:
|
||||
// convert texture format.
|
||||
if (m_input->m_presetSetting.m_swizzle.size() >= 4)
|
||||
{
|
||||
m_image->Get()->Swizzle(m_input->m_presetSetting.m_swizzle.substr(0, 4).c_str());
|
||||
m_alphaContent = m_image->Get()->GetAlphaContent();
|
||||
}
|
||||
|
||||
// convert gloss map (alhpa channel) from legacy distribution to new one
|
||||
if (m_input->m_presetSetting.m_isLegacyGloss)
|
||||
{
|
||||
m_image->Get()->ConvertLegacyGloss();
|
||||
}
|
||||
break;
|
||||
case StepCubemapLayout:
|
||||
// convert cubemap image's layout to vertical strip used in game.
|
||||
if (IsConvertToCubemap())
|
||||
{
|
||||
if (!m_image->ConvertCubemapLayout(CubemapLayoutVertical))
|
||||
{
|
||||
m_image->Set(nullptr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StepPreNormalize:
|
||||
// normalize base image before mipmap generation if glossfromnormals is enabled and require normalize
|
||||
if (m_input->m_presetSetting.m_isMipRenormalize && m_input->m_presetSetting.m_glossFromNormals)
|
||||
{
|
||||
// Normalize the base mip map. This has to be done explicitly because we need to disable mip renormalization to
|
||||
// preserve the normal length when deriving the normal variance
|
||||
m_image->Get()->NormalizeVectors(0, 1);
|
||||
}
|
||||
break;
|
||||
case StepMipmap:
|
||||
// generate mipmaps
|
||||
if (IsConvertToCubemap())
|
||||
@@ -304,20 +295,10 @@ namespace ImageProcessingAtom
|
||||
m_image->Get()->AddImageFlags(EIF_RenormalizedTexture);
|
||||
}
|
||||
break;
|
||||
case StepCreateHighPass:
|
||||
if (m_input->m_presetSetting.m_highPassMip > 0)
|
||||
{
|
||||
m_image->CreateHighPass(m_input->m_presetSetting.m_highPassMip);
|
||||
}
|
||||
break;
|
||||
case StepConvertOutputColorSpace:
|
||||
// convert image from linear space to desired output color space
|
||||
ConvertToOuputColorSpace();
|
||||
break;
|
||||
case StepAlphaImage:
|
||||
// save alpha channel to separate image if it's needed
|
||||
CreateAlphaImage();
|
||||
break;
|
||||
case StepConvertPixelFormat:
|
||||
// convert pixel format
|
||||
ConvertPixelformat();
|
||||
@@ -411,12 +392,6 @@ namespace ImageProcessingAtom
|
||||
return;
|
||||
}
|
||||
|
||||
// don't do any reduce for color chart
|
||||
if (presetSettings->m_isColorChart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get suitable size for dest pixel format
|
||||
CPixelFormats::GetInstance().GetSuitableImageSize(presetSettings->m_pixelFormat, inputWidth, inputHeight,
|
||||
outWidth, outHeight);
|
||||
@@ -510,52 +485,6 @@ namespace ImageProcessingAtom
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImageConvertProcess::CreateAlphaImage()
|
||||
{
|
||||
// if alpha content doesn't have alpha or we need to discard alpha, skip
|
||||
// we won't create alpha image for cubemap too
|
||||
if (m_alphaContent == EAlphaContent::eAlphaContent_Absent
|
||||
|| m_alphaContent == EAlphaContent::eAlphaContent_OnlyWhite
|
||||
|| m_input->m_presetSetting.m_discardAlpha || IsConvertToCubemap())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if dest format could save alpha, skip too
|
||||
if (!CPixelFormats::GetInstance().IsPixelFormatWithoutAlpha(m_input->m_presetSetting.m_pixelFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// now create alpha image
|
||||
ImageToProcess alphaImage(m_image->Get());
|
||||
alphaImage.ConvertFormat(ePixelFormat_A8);
|
||||
|
||||
// validate pixelformatalpha
|
||||
if (CPixelFormats::GetInstance().IsFormatSingleChannel(m_input->m_presetSetting.m_pixelFormatAlpha))
|
||||
{
|
||||
alphaImage.ConvertFormat(m_input->m_presetSetting.m_pixelFormatAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
//For ASTC compression we need to clear out the alpha to get accurate rgb compression.
|
||||
if (IsASTCFormat(m_input->m_presetSetting.m_pixelFormat))
|
||||
{
|
||||
alphaImage.ConvertFormat(ePixelFormat_R8G8B8X8);
|
||||
alphaImage.ConvertFormat(m_input->m_presetSetting.m_pixelFormatAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "PixelFormatAlpha only supports single channel pixel formats or ASTC formats");
|
||||
}
|
||||
}
|
||||
|
||||
// get final result and save it to member variable for later use
|
||||
m_alphaImage = alphaImage.Get();
|
||||
|
||||
m_image->Get()->AddImageFlags(EIF_AttachedAlpha);
|
||||
}
|
||||
|
||||
// pixel format conversion
|
||||
bool ImageConvertProcess::ConvertPixelformat()
|
||||
{
|
||||
@@ -575,12 +504,6 @@ namespace ImageProcessingAtom
|
||||
m_image->GetCompressOption().rgbWeight = m_input->m_presetSetting.GetColorWeight();
|
||||
m_image->GetCompressOption().discardAlpha = m_input->m_presetSetting.m_discardAlpha;
|
||||
|
||||
//For ASTC compression we need to clear out the alpha to get accurate rgb compression.
|
||||
if(m_alphaImage && IsASTCFormat(m_input->m_presetSetting.m_pixelFormat))
|
||||
{
|
||||
m_image->GetCompressOption().discardAlpha = true;
|
||||
}
|
||||
|
||||
m_image->ConvertFormat(m_input->m_presetSetting.m_pixelFormat);
|
||||
|
||||
return true;
|
||||
@@ -762,7 +685,6 @@ namespace ImageProcessingAtom
|
||||
if (ImageProcess##PrivateName::DoesSupport(m_input->m_platform)) \
|
||||
{ \
|
||||
ImageProcess##PrivateName::PrepareImageForExport(m_image->Get()); \
|
||||
ImageProcess##PrivateName::PrepareImageForExport(m_alphaImage); \
|
||||
}
|
||||
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
|
||||
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
|
||||
|
||||
Reference in New Issue
Block a user