Merge pull request #7406 from aws-lumberyard-dev/cgalvan/ImageGradientStreamingImageSupport
Updated the image gradient component to use a streaming image asset
This commit is contained in:
+2
-2
@@ -49,8 +49,7 @@ namespace ImageProcessingAtom
|
||||
static const unsigned int s_MinReduceLevel = 0;
|
||||
static const unsigned int s_MaxReduceLevel = 5;
|
||||
|
||||
static const int s_TotalSupportedImageExtensions = 10;
|
||||
static const char* s_SupportedImageExtensions[s_TotalSupportedImageExtensions] = {
|
||||
static const char* s_SupportedImageExtensions[] = {
|
||||
"*.tif",
|
||||
"*.tiff",
|
||||
"*.png",
|
||||
@@ -62,6 +61,7 @@ namespace ImageProcessingAtom
|
||||
"*.dds",
|
||||
"*.exr"
|
||||
};
|
||||
static constexpr int s_TotalSupportedImageExtensions = AZ_ARRAY_SIZE(s_SupportedImageExtensions);
|
||||
|
||||
enum class RGBWeight : AZ::u32
|
||||
{
|
||||
+1
-1
@@ -8,12 +8,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/BuilderSettings.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/PixelFormats.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include <AzCore/RTTI/TypeInfo.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/CubemapSettings.h>
|
||||
#include <BuilderSettings/MipmapSettings.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/PixelFormats.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Serialization/DataPatch.h>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Atom/ImageProcessing/PixelFormats.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
#include <QRect>
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/PresetSettings.h>
|
||||
#include <BuilderSettings/TextureSettings.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Compressors/Compressor.h>
|
||||
|
||||
#include <AzCore/Jobs/Job.h>
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/PresetSettings.h>
|
||||
#include <BuilderSettings/TextureSettings.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <AzCore/Jobs/Job.h>
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <Processing/PixelFormatInfo.h>
|
||||
#include <Processing/ImageConvert.h>
|
||||
#include <Processing/ImageToProcess.h>
|
||||
@@ -45,7 +46,6 @@
|
||||
|
||||
#include <BuilderSettings/BuilderSettingManager.h>
|
||||
#include <BuilderSettings/CubemapSettings.h>
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/PresetSettings.h>
|
||||
|
||||
#include <Editor/EditorCommon.h>
|
||||
|
||||
@@ -13,6 +13,7 @@ set(FILES
|
||||
Include/Atom/ImageProcessing/ImageProcessingEditorBus.h
|
||||
Include/Atom/ImageProcessing/PixelFormats.h
|
||||
Include/Atom/ImageProcessing/ImageObject.h
|
||||
Include/Atom/ImageProcessing/ImageProcessingDefines.h
|
||||
../Assets/Editor/Resources.qrc
|
||||
../Assets/Editor/Backward.png
|
||||
../Assets/Editor/Forward.png
|
||||
@@ -28,7 +29,6 @@ set(FILES
|
||||
Source/BuilderSettings/BuilderSettings.h
|
||||
Source/BuilderSettings/CubemapSettings.cpp
|
||||
Source/BuilderSettings/CubemapSettings.h
|
||||
Source/BuilderSettings/ImageProcessingDefines.h
|
||||
Source/BuilderSettings/MipmapSettings.cpp
|
||||
Source/BuilderSettings/MipmapSettings.h
|
||||
Source/BuilderSettings/PlatformSettings.h
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Include/Atom/ImageProcessing/ImageProcessingDefines.h
|
||||
)
|
||||
|
||||
@@ -133,7 +133,8 @@ namespace AZ
|
||||
case AZ::RHI::Format::R16G16_UNORM:
|
||||
case AZ::RHI::Format::R16G16B16A16_UNORM:
|
||||
{
|
||||
return mem[index] / static_cast<float>(std::numeric_limits<AZ::u16>::max());
|
||||
auto actualMem = reinterpret_cast<const AZ::u16*>(mem);
|
||||
return actualMem[index] / static_cast<float>(std::numeric_limits<AZ::u16>::max());
|
||||
}
|
||||
case AZ::RHI::Format::R16_SNORM:
|
||||
case AZ::RHI::Format::R16G16_SNORM:
|
||||
@@ -480,14 +481,13 @@ namespace AZ
|
||||
const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor();
|
||||
auto width = imageDescriptor.m_size.m_width;
|
||||
const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format);
|
||||
const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents;
|
||||
|
||||
size_t outValuesIndex = 0;
|
||||
for (uint32_t y = topLeft.second; y < bottomRight.second; ++y)
|
||||
{
|
||||
for (uint32_t x = topLeft.first; x < bottomRight.first; ++x)
|
||||
{
|
||||
size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex;
|
||||
size_t imageDataIndex = (y * width + x) * numComponents + componentIndex;
|
||||
|
||||
auto& outValue = outValues[outValuesIndex++];
|
||||
outValue = Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format);
|
||||
@@ -513,14 +513,13 @@ namespace AZ
|
||||
const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor();
|
||||
auto width = imageDescriptor.m_size.m_width;
|
||||
const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format);
|
||||
const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents;
|
||||
|
||||
size_t outValuesIndex = 0;
|
||||
for (uint32_t y = topLeft.second; y < bottomRight.second; ++y)
|
||||
{
|
||||
for (uint32_t x = topLeft.first; x < bottomRight.first; ++x)
|
||||
{
|
||||
size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex;
|
||||
size_t imageDataIndex = (y * width + x) * numComponents + componentIndex;
|
||||
|
||||
auto& outValue = outValues[outValuesIndex++];
|
||||
outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format);
|
||||
@@ -546,14 +545,13 @@ namespace AZ
|
||||
const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor();
|
||||
auto width = imageDescriptor.m_size.m_width;
|
||||
const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format);
|
||||
const uint32_t pixelSize = AZ::RHI::GetFormatSize(imageDescriptor.m_format) / numComponents;
|
||||
|
||||
size_t outValuesIndex = 0;
|
||||
for (uint32_t y = topLeft.second; y < bottomRight.second; ++y)
|
||||
{
|
||||
for (uint32_t x = topLeft.first; x < bottomRight.first; ++x)
|
||||
{
|
||||
size_t imageDataIndex = (y * width + x) * pixelSize + componentIndex;
|
||||
size_t imageDataIndex = (y * width + x) * numComponents + componentIndex;
|
||||
|
||||
auto& outValue = outValues[outValuesIndex++];
|
||||
outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format);
|
||||
|
||||
@@ -17,9 +17,12 @@ ly_add_target(
|
||||
PUBLIC
|
||||
Include
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AtomCore
|
||||
PUBLIC
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
Gem::Atom_RPI.Public
|
||||
Gem::SurfaceData
|
||||
Gem::ImageProcessingAtom.Headers
|
||||
Gem::LmbrCentral
|
||||
|
||||
+17
-1
@@ -8,8 +8,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <GradientSignal/Ebuses/GradientRequestBus.h>
|
||||
#include <GradientSignal/Ebuses/GradientTransformRequestBus.h>
|
||||
#include <GradientSignal/Ebuses/ImageGradientRequestBus.h>
|
||||
@@ -25,6 +28,19 @@ namespace LmbrCentral
|
||||
|
||||
namespace GradientSignal
|
||||
{
|
||||
// Custom JSON serializer for ImageGradientConfig to handle version conversion
|
||||
class JsonImageGradientConfigSerializer
|
||||
: public AZ::BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(GradientSignal::JsonImageGradientConfigSerializer, "{C5B982C8-2E81-45C3-8932-B6F54B28F493}", AZ::BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
AZ::JsonSerializationResult::Result Load(
|
||||
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
AZ::JsonDeserializerContext& context) override;
|
||||
};
|
||||
|
||||
class ImageGradientConfig
|
||||
: public AZ::ComponentConfig
|
||||
{
|
||||
@@ -32,7 +48,7 @@ namespace GradientSignal
|
||||
AZ_CLASS_ALLOCATOR(ImageGradientConfig, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(ImageGradientConfig, "{1BDB5DA4-A4A8-452B-BE6D-6BD451D4E7CD}", AZ::ComponentConfig);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
AZ::Data::Asset<ImageAsset> m_imageAsset = { AZ::Data::AssetLoadBehavior::QueueLoad };
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> m_imageAsset = { AZ::Data::AssetLoadBehavior::QueueLoad };
|
||||
float m_tilingX = 1.0f;
|
||||
float m_tilingY = 1.0f;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzFramework/Asset/GenericAssetHandler.h>
|
||||
#include <Atom/ImageProcessing/PixelFormats.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -61,6 +62,6 @@ namespace GradientSignal
|
||||
}
|
||||
};
|
||||
|
||||
float GetValueFromImageAsset(const AZ::Data::Asset<ImageAsset>& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue);
|
||||
float GetValueFromImageAsset(const AZ::Data::Asset<AZ::RPI::StreamingImageAsset>& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue);
|
||||
|
||||
} // namespace GradientSignal
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <GradientSignal/Components/ImageGradientComponent.h>
|
||||
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
@@ -18,16 +19,103 @@
|
||||
|
||||
namespace GradientSignal
|
||||
{
|
||||
AZ::JsonSerializationResult::Result JsonImageGradientConfigSerializer::Load(
|
||||
void* outputValue, [[maybe_unused]] const AZ::Uuid& outputValueTypeId,
|
||||
const rapidjson::Value& inputValue, AZ::JsonDeserializerContext& context)
|
||||
{
|
||||
// We can distinguish between version 1 and 2 by the presence of the "ImageAsset" field,
|
||||
// which is only in version 1.
|
||||
// For version 2, we don't need to do any special processing, so just let the base class
|
||||
// load the JSON if we don't find the "ImageAsset" field.
|
||||
rapidjson::Value::ConstMemberIterator itr = inputValue.FindMember("ImageAsset");
|
||||
if (itr == inputValue.MemberEnd())
|
||||
{
|
||||
return AZ::BaseJsonSerializer::Load(outputValue, outputValueTypeId, inputValue, context);
|
||||
}
|
||||
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
auto configInstance = reinterpret_cast<ImageGradientConfig*>(outputValue);
|
||||
AZ_Assert(configInstance, "Output value for JsonImageGradientConfigSerializer can't be null.");
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::ReadField);
|
||||
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(
|
||||
&configInstance->m_tilingX, azrtti_typeid<decltype(configInstance->m_tilingX)>(), inputValue, "TilingX", context));
|
||||
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(
|
||||
&configInstance->m_tilingY, azrtti_typeid<decltype(configInstance->m_tilingY)>(), inputValue, "TilingY", context));
|
||||
|
||||
// Version 1 stored a custom GradientSignal::ImageAsset as the image asset.
|
||||
// In Version 2, we changed the image asset to use the generic AZ::RPI::StreamingImageAsset,
|
||||
// so they are both AZ::Data::Asset but reference different types.
|
||||
// Using the assetHint, which will be something like "my_test_image.gradimage",
|
||||
// we need to find the valid streaming image asset product from the same source,
|
||||
// which will be something like "my_test_image.png.streamingimage"
|
||||
AZStd::string assetHint;
|
||||
AZ::Data::AssetId fixedAssetId;
|
||||
auto it = itr->value.FindMember("assetHint");
|
||||
if (it != itr->value.MemberEnd())
|
||||
{
|
||||
AZ::ScopedContextPath subPath(context, "assetHint");
|
||||
result.Combine(ContinueLoading(&assetHint, azrtti_typeid<AZStd::string>(), it->value, context));
|
||||
|
||||
if (assetHint.ends_with(".gradimage"))
|
||||
{
|
||||
// We don't know what image format the original source was, so we need to loop through
|
||||
// all the supported image extensions to check if they have a valid corresponding
|
||||
// streaming image asset
|
||||
for (auto& supportedImageExtension : ImageProcessingAtom::s_SupportedImageExtensions)
|
||||
{
|
||||
AZStd::string imageExtension(supportedImageExtension);
|
||||
|
||||
// The image extensions are stored with a wildcard (e.g. *.png) so we need to strip that off first
|
||||
AZ::StringFunc::Replace(imageExtension, "*", "");
|
||||
|
||||
// Form potential streaming image path (e.g. my_test_image.png.streamingimage)
|
||||
AZStd::string potentialStreamingImagePath(assetHint);
|
||||
AZ::StringFunc::Replace(potentialStreamingImagePath, ".gradimage", "");
|
||||
potentialStreamingImagePath += imageExtension + ".streamingimage";
|
||||
|
||||
// Check if there is a valid streaming image asset for this path
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(fixedAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, potentialStreamingImagePath.c_str(), azrtti_typeid<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(), false);
|
||||
if (fixedAssetId.IsValid())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the old gradimage with new AssetId for streaming image asset
|
||||
if (fixedAssetId.IsValid())
|
||||
{
|
||||
configInstance->m_imageAsset = AZ::Data::AssetManager::Instance().GetAsset<AZ::RPI::StreamingImageAsset>(fixedAssetId, AZ::Data::AssetLoadBehavior::QueueLoad);
|
||||
}
|
||||
|
||||
return context.Report(result,
|
||||
result.GetProcessing() != JSR::Processing::Halted ?
|
||||
"Successfully loaded ImageGradientConfig information." :
|
||||
"Failed to load ImageGradientConfig information.");
|
||||
}
|
||||
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JsonImageGradientConfigSerializer, AZ::SystemAllocator, 0);
|
||||
|
||||
void ImageGradientConfig::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
|
||||
{
|
||||
jsonContext->Serializer<JsonImageGradientConfigSerializer>()->HandlesType<ImageGradientConfig>();
|
||||
}
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<ImageGradientConfig, AZ::ComponentConfig>()
|
||||
->Version(1)
|
||||
->Field("ImageAsset", &ImageGradientConfig::m_imageAsset)
|
||||
->Version(2)
|
||||
->Field("TilingX", &ImageGradientConfig::m_tilingX)
|
||||
->Field("TilingY", &ImageGradientConfig::m_tilingY)
|
||||
->Field("StreamingImageAsset", &ImageGradientConfig::m_imageAsset)
|
||||
;
|
||||
|
||||
AZ::EditContext* edit = serialize->GetEditContext();
|
||||
@@ -265,7 +353,7 @@ namespace GradientSignal
|
||||
|
||||
{
|
||||
AZStd::unique_lock<decltype(m_imageMutex)> imageLock(m_imageMutex);
|
||||
m_configuration.m_imageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(assetId, azrtti_typeid<ImageAsset>(), m_configuration.m_imageAsset.GetAutoLoadBehavior());
|
||||
m_configuration.m_imageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(assetId, azrtti_typeid<AZ::RPI::StreamingImageAsset>(), m_configuration.m_imageAsset.GetAutoLoadBehavior());
|
||||
}
|
||||
|
||||
SetupDependencies();
|
||||
|
||||
@@ -15,84 +15,10 @@
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
|
||||
#include <Atom/ImageProcessing/PixelFormats.h>
|
||||
#include <Atom/RPI.Public/RPIUtils.h>
|
||||
#include <GradientSignal/Util.h>
|
||||
#include <numeric>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <ImageProcessingAtom::EPixelFormat>
|
||||
float RetrieveValue(const AZ::u8* mem, size_t index)
|
||||
{
|
||||
AZ_Assert(false, "Unimplemented!");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
template <>
|
||||
float RetrieveValue<ImageProcessingAtom::EPixelFormat::ePixelFormat_Unknown>([[maybe_unused]] const AZ::u8* mem, [[maybe_unused]] size_t index)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
template <>
|
||||
float RetrieveValue<ImageProcessingAtom::EPixelFormat::ePixelFormat_R8>(const AZ::u8* mem, size_t index)
|
||||
{
|
||||
return mem[index] / static_cast<float>(std::numeric_limits<AZ::u8>::max());
|
||||
}
|
||||
|
||||
template <>
|
||||
float RetrieveValue<ImageProcessingAtom::EPixelFormat::ePixelFormat_R16>(const AZ::u8* mem, size_t index)
|
||||
{
|
||||
// 16 bits per channel
|
||||
auto actualMem = reinterpret_cast<const AZ::u16*>(mem);
|
||||
actualMem += index;
|
||||
|
||||
return *actualMem / static_cast<float>(std::numeric_limits<AZ::u16>::max());
|
||||
}
|
||||
|
||||
template <>
|
||||
float RetrieveValue<ImageProcessingAtom::EPixelFormat::ePixelFormat_R32>(const AZ::u8* mem, size_t index)
|
||||
{
|
||||
// 32 bits per channel
|
||||
auto actualMem = reinterpret_cast<const AZ::u32*>(mem);
|
||||
actualMem += index;
|
||||
|
||||
return *actualMem / static_cast<float>(std::numeric_limits<AZ::u32>::max());
|
||||
}
|
||||
|
||||
template <>
|
||||
float RetrieveValue<ImageProcessingAtom::EPixelFormat::ePixelFormat_R32F>(const AZ::u8* mem, size_t index)
|
||||
{
|
||||
// 32 bits per channel
|
||||
auto actualMem = reinterpret_cast<const float*>(mem);
|
||||
actualMem += index;
|
||||
|
||||
return *actualMem;
|
||||
}
|
||||
|
||||
float RetrieveValue(const AZ::u8* mem, size_t index, ImageProcessingAtom::EPixelFormat format)
|
||||
{
|
||||
using namespace ImageProcessingAtom;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case ePixelFormat_R8:
|
||||
return RetrieveValue<ePixelFormat_R8>(mem, index);
|
||||
|
||||
case ePixelFormat_R16:
|
||||
return RetrieveValue<ePixelFormat_R16>(mem, index);
|
||||
|
||||
case ePixelFormat_R32:
|
||||
return RetrieveValue<ePixelFormat_R32>(mem, index);
|
||||
|
||||
case ePixelFormat_R32F:
|
||||
return RetrieveValue<ePixelFormat_R32F>(mem, index);
|
||||
|
||||
default:
|
||||
return RetrieveValue<ePixelFormat_Unknown>(mem, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace GradientSignal
|
||||
{
|
||||
void ImageAsset::Reflect(AZ::ReflectContext* context)
|
||||
@@ -152,17 +78,15 @@ namespace GradientSignal
|
||||
return true;
|
||||
}
|
||||
|
||||
float GetValueFromImageAsset(const AZ::Data::Asset<ImageAsset>& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue)
|
||||
float GetValueFromImageAsset(const AZ::Data::Asset<AZ::RPI::StreamingImageAsset>& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue)
|
||||
{
|
||||
if (imageAsset.IsReady())
|
||||
{
|
||||
const auto& image = imageAsset.Get();
|
||||
AZStd::size_t imageSize = image->m_imageWidth * image->m_imageHeight *
|
||||
static_cast<AZ::u32>(image->m_bytesPerPixel);
|
||||
|
||||
if (image->m_imageWidth > 0 &&
|
||||
image->m_imageHeight > 0 &&
|
||||
image->m_imageData.size() == imageSize)
|
||||
auto imageDescriptor = imageAsset->GetImageDescriptor();
|
||||
auto width = imageDescriptor.m_size.m_width;
|
||||
auto height = imageDescriptor.m_size.m_height;
|
||||
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
// When "rasterizing" from uvs, a range of 0-1 has slightly different meanings depending on the sampler state.
|
||||
// For repeating states (Unbounded/None, Repeat), a uv value of 1 should wrap around back to our 0th pixel.
|
||||
@@ -185,8 +109,8 @@ namespace GradientSignal
|
||||
// A 16x16 pixel image and tilingX = tilingY = 1 maps the uv range of 0-1 to 0-16 pixels.
|
||||
// A 16x16 pixel image and tilingX = tilingY = 1.5 maps the uv range of 0-1 to 0-24 pixels.
|
||||
|
||||
const AZ::Vector3 tiledDimensions((image->m_imageWidth * tilingX),
|
||||
(image->m_imageHeight * tilingY),
|
||||
const AZ::Vector3 tiledDimensions((width * tilingX),
|
||||
(height * tilingY),
|
||||
0.0f);
|
||||
|
||||
// Convert from uv space back to pixel space
|
||||
@@ -195,13 +119,13 @@ namespace GradientSignal
|
||||
// UVs outside the 0-1 range are treated as infinitely tiling, so that we behave the same as the
|
||||
// other gradient generators. As mentioned above, if clamping is desired, we expect it to be applied
|
||||
// outside of this function.
|
||||
size_t x = static_cast<size_t>(pixelLookup.GetX()) % image->m_imageWidth;
|
||||
size_t y = static_cast<size_t>(pixelLookup.GetY()) % image->m_imageHeight;
|
||||
auto x = aznumeric_cast<AZ::u32>(pixelLookup.GetX()) % width;
|
||||
auto y = aznumeric_cast<AZ::u32>(pixelLookup.GetY()) % height;
|
||||
|
||||
// Flip the y because images are stored in reverse of our world axes
|
||||
size_t index = ((image->m_imageHeight - 1) - y) * image->m_imageWidth + x;
|
||||
y = (height - 1) - y;
|
||||
|
||||
return RetrieveValue(image->m_imageData.data(), index, image->m_imageFormat);
|
||||
return AZ::RPI::GetSubImagePixelValue<float>(imageAsset, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
#include <Tests/GradientSignalTestFixtures.h>
|
||||
#include <Tests/GradientSignalTestHelpers.h>
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
@@ -88,7 +89,7 @@ namespace UnitTest
|
||||
|
||||
// Create the Image Gradient Component.
|
||||
GradientSignal::ImageGradientConfig config;
|
||||
config.m_imageAsset = ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset(
|
||||
config.m_imageAsset = UnitTest::CreateSpecificPixelImageAsset(
|
||||
test.m_imageSize, test.m_imageSize, static_cast<AZ::u32>(test.m_pixel.GetX()), static_cast<AZ::u32>(test.m_pixel.GetY()));
|
||||
config.m_tilingX = test.m_tiling;
|
||||
config.m_tilingY = test.m_tiling;
|
||||
@@ -379,7 +380,7 @@ namespace UnitTest
|
||||
|
||||
// Create an ImageGradient with a 3x3 asset with the center pixel set.
|
||||
GradientSignal::ImageGradientConfig gradientConfig;
|
||||
gradientConfig.m_imageAsset = ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset(3, 3, 1, 1);
|
||||
gradientConfig.m_imageAsset = UnitTest::CreateSpecificPixelImageAsset(3, 3, 1, 1);
|
||||
entity->CreateComponent<GradientSignal::ImageGradientComponent>(gradientConfig);
|
||||
|
||||
// Create the test GradientTransform
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
|
||||
#include <Tests/GradientSignalTestFixtures.h>
|
||||
#include <Tests/GradientSignalTestHelpers.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Image/ImageMipChainAsset.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <GradientSignal/Components/GradientSurfaceDataComponent.h>
|
||||
#include <GradientSignal/Components/GradientTransformComponent.h>
|
||||
@@ -74,14 +77,16 @@ namespace UnitTest
|
||||
|
||||
void GradientSignalBaseFixture::SetupCoreSystems()
|
||||
{
|
||||
m_mockHandler = new UnitTest::ImageAssetMockAssetHandler();
|
||||
AZ::Data::AssetManager::Instance().RegisterHandler(m_mockHandler, azrtti_typeid<GradientSignal::ImageAsset>());
|
||||
// Using the AZ::RPI::MakeAssetHandler will both create the asset handlers,
|
||||
// and register them with the AssetManager
|
||||
m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler<AZ::RPI::ImageMipChainAssetHandler>());
|
||||
m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler<AZ::RPI::StreamingImageAssetHandler>());
|
||||
}
|
||||
|
||||
void GradientSignalBaseFixture::TearDownCoreSystems()
|
||||
{
|
||||
AZ::Data::AssetManager::Instance().UnregisterHandler(m_mockHandler);
|
||||
delete m_mockHandler; // delete after removing from the asset manager
|
||||
// This will delete the asset handlers, which will unregister themselves on deletion
|
||||
m_assetHandlers.clear();
|
||||
|
||||
AzFramework::LegacyAssetEventBus::ClearQueuedEvents();
|
||||
}
|
||||
@@ -139,7 +144,7 @@ namespace UnitTest
|
||||
GradientSignal::ImageGradientConfig config;
|
||||
const uint32_t imageSize = 4096;
|
||||
const int32_t imageSeed = 12345;
|
||||
config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed);
|
||||
config.m_imageAsset = UnitTest::CreateImageAsset(imageSize, imageSize, imageSeed);
|
||||
config.m_tilingX = 1.0f;
|
||||
config.m_tilingY = 1.0f;
|
||||
entity->CreateComponent<GradientSignal::ImageGradientComponent>(config);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <Tests/GradientSignalTestMocks.h>
|
||||
#include <LmbrCentral/Shape/MockShapes.h>
|
||||
#include <Atom/RPI.Reflect/Asset/AssetHandler.h>
|
||||
#include <AzTest/GemTestEnvironment.h>
|
||||
|
||||
namespace UnitTest
|
||||
@@ -89,7 +90,7 @@ namespace UnitTest
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSurfaceMaskGradient(float shapeHalfBounds);
|
||||
AZStd::unique_ptr<AZ::Entity> BuildTestSurfaceSlopeGradient(float shapeHalfBounds);
|
||||
|
||||
UnitTest::ImageAssetMockAssetHandler* m_mockHandler = nullptr;
|
||||
AZ::RPI::AssetHandlerPtrList m_assetHandlers;
|
||||
};
|
||||
|
||||
struct GradientSignalTest
|
||||
|
||||
@@ -8,11 +8,189 @@
|
||||
|
||||
|
||||
#include <Tests/GradientSignalTestHelpers.h>
|
||||
#include <Atom/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <GradientSignal/GradientSampler.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
AZ::RHI::ImageSubresourceLayout BuildSubImageLayout(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize)
|
||||
{
|
||||
AZ::RHI::ImageSubresourceLayout layout;
|
||||
layout.m_size = AZ::RHI::Size{ width, height, 1 };
|
||||
layout.m_rowCount = width;
|
||||
layout.m_bytesPerRow = width * pixelSize;
|
||||
layout.m_bytesPerImage = width * height * pixelSize;
|
||||
return layout;
|
||||
}
|
||||
|
||||
AZStd::vector<uint8_t> BuildBasicImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed)
|
||||
{
|
||||
const size_t imageSize = width * height * pixelSize;
|
||||
|
||||
AZStd::vector<uint8_t> image;
|
||||
image.reserve(imageSize);
|
||||
|
||||
size_t value = 0;
|
||||
AZStd::hash_combine(value, seed);
|
||||
|
||||
for (AZ::u32 x = 0; x < width; ++x)
|
||||
{
|
||||
for (AZ::u32 y = 0; y < height; ++y)
|
||||
{
|
||||
AZStd::hash_combine(value, x);
|
||||
AZStd::hash_combine(value, y);
|
||||
image.push_back(static_cast<AZ::u8>(value));
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(image.size(), imageSize);
|
||||
return image;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> BuildBasicMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed)
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
RPI::ImageMipChainAssetCreator assetCreator;
|
||||
|
||||
assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), mipLevels, arraySize);
|
||||
|
||||
RHI::ImageSubresourceLayout layout = BuildSubImageLayout(width, height, pixelSize);
|
||||
|
||||
assetCreator.BeginMip(layout);
|
||||
|
||||
for (AZ::u32 arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = BuildBasicImageData(width, height, pixelSize, seed);
|
||||
assetCreator.AddSubImage(data.data(), data.size());
|
||||
}
|
||||
|
||||
assetCreator.EndMip();
|
||||
|
||||
Data::Asset<RPI::ImageMipChainAsset> asset;
|
||||
EXPECT_TRUE(assetCreator.End(asset));
|
||||
EXPECT_TRUE(asset.IsReady());
|
||||
EXPECT_NE(asset.Get(), nullptr);
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
AZStd::vector<uint8_t> BuildSpecificPixelImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY)
|
||||
{
|
||||
const size_t imageSize = width * height * pixelSize;
|
||||
|
||||
AZStd::vector<uint8_t> image;
|
||||
image.reserve(imageSize);
|
||||
|
||||
const AZ::u8 pixelValue = 255;
|
||||
|
||||
// Image data should be stored inverted on the y axis relative to our engine, so loop backwards through y.
|
||||
for (int y = static_cast<int>(height) - 1; y >= 0; --y)
|
||||
{
|
||||
for (AZ::u32 x = 0; x < width; ++x)
|
||||
{
|
||||
if ((x == static_cast<int>(pixelX)) && (y == static_cast<int>(pixelY)))
|
||||
{
|
||||
image.push_back(pixelValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
image.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(image.size(), imageSize);
|
||||
return image;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> BuildSpecificPixelMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY)
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
RPI::ImageMipChainAssetCreator assetCreator;
|
||||
|
||||
assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()), mipLevels, arraySize);
|
||||
|
||||
RHI::ImageSubresourceLayout layout = BuildSubImageLayout(width, height, pixelSize);
|
||||
|
||||
assetCreator.BeginMip(layout);
|
||||
|
||||
for (AZ::u32 arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = BuildSpecificPixelImageData(width, height, pixelSize, pixelX, pixelY);
|
||||
assetCreator.AddSubImage(data.data(), data.size());
|
||||
}
|
||||
|
||||
assetCreator.EndMip();
|
||||
|
||||
Data::Asset<RPI::ImageMipChainAsset> asset;
|
||||
EXPECT_TRUE(assetCreator.End(asset));
|
||||
EXPECT_TRUE(asset.IsReady());
|
||||
EXPECT_NE(asset.Get(), nullptr);
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed)
|
||||
{
|
||||
auto randomAssetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom());
|
||||
auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset<AZ::RPI::StreamingImageAsset>(
|
||||
randomAssetId, AZ::Data::AssetLoadBehavior::Default);
|
||||
|
||||
const AZ::u32 arraySize = 1;
|
||||
const AZ::u32 mipCountTotal = 1;
|
||||
const auto format = AZ::RHI::Format::R8_UNORM;
|
||||
const AZ::u32 pixelSize = AZ::RHI::GetFormatComponentCount(format);
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> mipChain = BuildBasicMipChainAsset(mipCountTotal, arraySize, width, height, pixelSize, seed);
|
||||
|
||||
AZ::RPI::StreamingImageAssetCreator assetCreator;
|
||||
assetCreator.Begin(randomAssetId);
|
||||
|
||||
AZ::RHI::ImageDescriptor imageDesc = AZ::RHI::ImageDescriptor::Create2DArray(AZ::RHI::ImageBindFlags::ShaderRead, width, height, arraySize, format);
|
||||
imageDesc.m_mipLevels = static_cast<AZ::u16>(mipCountTotal);
|
||||
|
||||
assetCreator.SetImageDescriptor(imageDesc);
|
||||
assetCreator.AddMipChainAsset(*mipChain.Get());
|
||||
|
||||
EXPECT_TRUE(assetCreator.End(imageAsset));
|
||||
EXPECT_TRUE(imageAsset.IsReady());
|
||||
EXPECT_NE(imageAsset.Get(), nullptr);
|
||||
|
||||
return imageAsset;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateSpecificPixelImageAsset(AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY)
|
||||
{
|
||||
auto randomAssetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom());
|
||||
auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset<AZ::RPI::StreamingImageAsset>(
|
||||
randomAssetId, AZ::Data::AssetLoadBehavior::Default);
|
||||
|
||||
const AZ::u32 arraySize = 1;
|
||||
const AZ::u32 mipCountTotal = 1;
|
||||
const auto format = AZ::RHI::Format::R8_UNORM;
|
||||
const AZ::u32 pixelSize = AZ::RHI::GetFormatComponentCount(format);
|
||||
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> mipChain = BuildSpecificPixelMipChainAsset(mipCountTotal, arraySize, width, height, pixelSize, pixelX, pixelY);
|
||||
|
||||
AZ::RPI::StreamingImageAssetCreator assetCreator;
|
||||
assetCreator.Begin(randomAssetId);
|
||||
|
||||
AZ::RHI::ImageDescriptor imageDesc = AZ::RHI::ImageDescriptor::Create2DArray(AZ::RHI::ImageBindFlags::ShaderRead, width, height, arraySize, format);
|
||||
imageDesc.m_mipLevels = static_cast<AZ::u16>(mipCountTotal);
|
||||
|
||||
assetCreator.SetImageDescriptor(imageDesc);
|
||||
assetCreator.AddMipChainAsset(*mipChain.Get());
|
||||
|
||||
EXPECT_TRUE(assetCreator.End(imageAsset));
|
||||
EXPECT_TRUE(imageAsset.IsReady());
|
||||
EXPECT_NE(imageAsset.Get(), nullptr);
|
||||
return imageAsset;
|
||||
}
|
||||
|
||||
void GradientSignalTestHelpers::CompareGetValueAndGetValues(AZ::EntityId gradientEntityId, float queryMin, float queryMax)
|
||||
{
|
||||
// Create a gradient sampler and run through a series of points to see if they match expectations.
|
||||
|
||||
@@ -12,8 +12,72 @@
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <Atom/RHI.Reflect/ImageSubresource.h>
|
||||
#include <Atom/RPI.Reflect/Image/ImageMipChainAsset.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
//! Helper method to build a AZ::RHI::ImageSubresourceLayout
|
||||
//! @param width The width of the image
|
||||
//! @param height The height of the image
|
||||
//! @param pixelSize Number of bytes per pixel
|
||||
//! @return The AZ::RHI::ImageSubresourceLayout that has been filled out appropriately
|
||||
AZ::RHI::ImageSubresourceLayout BuildSubImageLayout(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize);
|
||||
|
||||
//! Build a deterministic random set of image pixel data
|
||||
//! @param width Width of the image
|
||||
//! @param height Height of the image
|
||||
//! @param pixelSize Number of bytes per pixel
|
||||
//! @param seed The random seed for generating the data
|
||||
//! @return A vector of bytes for the image data
|
||||
AZStd::vector<uint8_t> BuildBasicImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed);
|
||||
|
||||
//! Build a mip chain asset that contains the basic image data from BuildBasicImageData
|
||||
//! @param mipLevels Number of mip levels in the chain
|
||||
//! @param arraySize Number of sub images within a mip level
|
||||
//! @param width The width of the image
|
||||
//! @param height The height of the image
|
||||
//! @param pixelSize The number of bytes per pixel
|
||||
//! @param seed The random seed for generating the data
|
||||
//! @return A mip chain asset with the specified basic image data
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> BuildBasicMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::s32 seed);
|
||||
|
||||
//! Construct an array of image data where all the pixels are 0 except for one at the given coordinate
|
||||
//! @param width Width of the image
|
||||
//! @param height Height of the image
|
||||
//! @param pixelSize Number of bytes per pixel
|
||||
//! @param pixelX The X coordinate of the pixel to set to 1
|
||||
//! @param pixelY The Y coordinate of the pixel to set to 1
|
||||
//! @return A vector of bytes for the image data
|
||||
AZStd::vector<uint8_t> BuildSpecificPixelImageData(AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY);
|
||||
|
||||
//! Build a mip chain asset that contains the specific image data from BuildSpecificPixelImageData
|
||||
//! @param mipLevels Number of mip levels in the chain
|
||||
//! @param arraySize Number of sub images within a mip level
|
||||
//! @param width The width of the image
|
||||
//! @param height The height of the image
|
||||
//! @param pixelSize The number of bytes per pixel
|
||||
//! @param pixelX The X coordinate of the pixel to set to 1
|
||||
//! @param pixelY The Y coordinate of the pixel to set to 1
|
||||
//! @return A mip chain asset with the specific pixel image data
|
||||
AZ::Data::Asset<AZ::RPI::ImageMipChainAsset> BuildSpecificPixelMipChainAsset(AZ::u16 mipLevels, AZ::u16 arraySize, AZ::u32 width, AZ::u32 height, AZ::u32 pixelSize, AZ::u32 pixelX, AZ::u32 pixelY);
|
||||
|
||||
//! Creates a deterministically random set of pixel data as an AZ::RPI::StreamingImageAsset.
|
||||
//! \param width The width of the AZ::RPI::StreamingImageAsset
|
||||
//! \param height The height of the AZ::RPI::StreamingImageAsset
|
||||
//! \param seed The random seed to use for generating the random data
|
||||
//! \return The AZ::RPI::StreamingImageAsset in a loaded ready state
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed);
|
||||
|
||||
//! Creates an AZ::RPI::StreamingImageAsset where all the pixels are 0 except for the one pixel at the given coordinates, which is set to 1.
|
||||
//! \param width The width of the AZ::RPI::StreamingImageAsset
|
||||
//! \param height The height of the AZ::RPI::StreamingImageAsset
|
||||
//! \param pixelX The X coordinate of the pixel to set to 1
|
||||
//! \param pixelY The Y coordinate of the pixel to set to 1
|
||||
//! \return The AZ::RPI::StreamingImageAsset in a loaded ready state
|
||||
AZ::Data::Asset<AZ::RPI::StreamingImageAsset> CreateSpecificPixelImageAsset(AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY);
|
||||
|
||||
class GradientSignalTestHelpers
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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 <Tests/GradientSignalTestMocks.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
AZ::Data::Asset<GradientSignal::ImageAsset> ImageAssetMockAssetHandler::CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed)
|
||||
{
|
||||
auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset<GradientSignal::ImageAsset>(
|
||||
AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default);
|
||||
|
||||
imageAsset->m_imageWidth = width;
|
||||
imageAsset->m_imageHeight = height;
|
||||
imageAsset->m_bytesPerPixel = 1;
|
||||
imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8;
|
||||
imageAsset->m_imageData.reserve(width * height);
|
||||
|
||||
size_t value = 0;
|
||||
AZStd::hash_combine(value, seed);
|
||||
|
||||
for (AZ::u32 x = 0; x < width; ++x)
|
||||
{
|
||||
for (AZ::u32 y = 0; y < height; ++y)
|
||||
{
|
||||
AZStd::hash_combine(value, x);
|
||||
AZStd::hash_combine(value, y);
|
||||
imageAsset->m_imageData.push_back(static_cast<AZ::u8>(value));
|
||||
}
|
||||
}
|
||||
|
||||
return imageAsset;
|
||||
}
|
||||
|
||||
AZ::Data::Asset<GradientSignal::ImageAsset> ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset(
|
||||
AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY)
|
||||
{
|
||||
auto imageAsset = AZ::Data::AssetManager::Instance().CreateAsset<GradientSignal::ImageAsset>(
|
||||
AZ::Data::AssetId(AZ::Uuid::CreateRandom()), AZ::Data::AssetLoadBehavior::Default);
|
||||
|
||||
imageAsset->m_imageWidth = width;
|
||||
imageAsset->m_imageHeight = height;
|
||||
imageAsset->m_bytesPerPixel = 1;
|
||||
imageAsset->m_imageFormat = ImageProcessingAtom::EPixelFormat::ePixelFormat_R8;
|
||||
imageAsset->m_imageData.reserve(width * height);
|
||||
|
||||
const AZ::u8 pixelValue = 255;
|
||||
|
||||
// Image data should be stored inverted on the y axis relative to our engine, so loop backwards through y.
|
||||
for (int y = static_cast<int>(height) - 1; y >= 0; --y)
|
||||
{
|
||||
for (AZ::u32 x = 0; x < width; ++x)
|
||||
{
|
||||
if ((x == static_cast<int>(pixelX)) && (y == static_cast<int>(pixelY)))
|
||||
{
|
||||
imageAsset->m_imageData.push_back(pixelValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
imageAsset->m_imageData.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return imageAsset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,53 +28,6 @@
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
// Mock asset handler for GradientSignal::ImageAsset that we can use in unit tests to pretend to load an image asset with.
|
||||
// Also includes utility functions for creating image assets with specific testable patterns.
|
||||
struct ImageAssetMockAssetHandler : public AZ::Data::AssetHandler
|
||||
{
|
||||
//! Creates a deterministically random set of pixel data as an ImageAsset.
|
||||
//! \param width The width of the ImageAsset
|
||||
//! \param height The height of the ImageAsset
|
||||
//! \param seed The random seed to use for generating the random data
|
||||
//! \return The ImageAsset in a loaded ready state
|
||||
static AZ::Data::Asset<GradientSignal::ImageAsset> CreateImageAsset(AZ::u32 width, AZ::u32 height, AZ::s32 seed);
|
||||
|
||||
//! Creates an ImageAsset where all the pixels are 0 except for the one pixel at the given coordinates, which is set to 1.
|
||||
//! \param width The width of the ImageAsset
|
||||
//! \param height The height of the ImageAsset
|
||||
//! \param pixelX The X coordinate of the pixel to set to 1
|
||||
//! \param pixelY The Y coordinate of the pixel to set to 1
|
||||
//! \return The ImageAsset in a loaded ready state
|
||||
static AZ::Data::Asset<GradientSignal::ImageAsset> CreateSpecificPixelImageAsset(
|
||||
AZ::u32 width, AZ::u32 height, AZ::u32 pixelX, AZ::u32 pixelY);
|
||||
|
||||
AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override
|
||||
{
|
||||
// For our mock handler, always mark our assets as immediately ready.
|
||||
return aznew GradientSignal::ImageAsset(id, AZ::Data::AssetData::AssetStatus::Ready);
|
||||
}
|
||||
|
||||
void DestroyAsset(AZ::Data::AssetPtr ptr) override
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GetHandledAssetTypes([[maybe_unused]] AZStd::vector<AZ::Data::AssetType>& assetTypes) override
|
||||
{
|
||||
}
|
||||
|
||||
AZ::Data::AssetHandler::LoadResult LoadAssetData(
|
||||
[[maybe_unused]] const AZ::Data::Asset<AZ::Data::AssetData>& asset,
|
||||
[[maybe_unused]] AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
|
||||
[[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override
|
||||
{
|
||||
return AZ::Data::AssetHandler::LoadResult::LoadComplete;
|
||||
}
|
||||
};
|
||||
|
||||
struct MockGradientRequestsBus
|
||||
: public GradientSignal::GradientRequestBus::Handler
|
||||
{
|
||||
|
||||
@@ -11,6 +11,5 @@ set(FILES
|
||||
Tests/GradientSignalTestHelpers.h
|
||||
Tests/GradientSignalTestFixtures.cpp
|
||||
Tests/GradientSignalTestFixtures.h
|
||||
Tests/GradientSignalTestMocks.cpp
|
||||
Tests/GradientSignalTestMocks.h
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user