Moved GetValueFromImageAsset from ImageAsset to ImageGradientComponent

Signed-off-by: Chris Galvan <chgalvan@amazon.com>
monroegm-disable-blank-issue-2
Chris Galvan 4 years ago
parent 283fe216dc
commit b2c7cf4452

@ -99,6 +99,7 @@ namespace GradientSignal
void SetupDependencies();
void GetSubImageData();
float GetValueFromImageData(const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) const;
// ImageGradientRequestBus overrides...
AZStd::string GetImageAssetPath() const override;

@ -62,6 +62,4 @@ namespace GradientSignal
}
};
float GetValueFromImageAsset(AZStd::span<const uint8_t> imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue);
} // namespace GradientSignal

@ -8,6 +8,7 @@
#include <GradientSignal/Components/ImageGradientComponent.h>
#include <Atom/ImageProcessing/ImageProcessingDefines.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Debug/Profiler.h>
@ -226,6 +227,60 @@ namespace GradientSignal
m_imageData = m_configuration.m_imageAsset->GetSubImageData(0, 0);
}
float ImageGradientComponent::GetValueFromImageData(const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) const
{
if (!m_imageData.empty())
{
const AZ::RHI::ImageDescriptor& imageDescriptor = m_configuration.m_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.
// For clamping states (Clamp to Zero, Clamp to Edge), a uv value of 1 should point to the last pixel.
// We assume here that the code handling sampler states has handled this for us in the clamping cases
// by reducing our uv by a small delta value such that anything that wants the last pixel has a value
// just slightly less than 1.
// Keeping that in mind, we scale our uv from 0-1 to 0-image size inclusive. So a 4-pixel image will scale
// uv values of 0-1 to 0-4, not 0-3 as you might expect. This is because we want the following range mappings:
// [0 - 1/4) = pixel 0
// [1/4 - 1/2) = pixel 1
// [1/2 - 3/4) = pixel 2
// [3/4 - 1) = pixel 3
// [1 - 1 1/4) = pixel 0
// ...
// Also, based on our tiling settings, we extend the size of our image virtually by a factor of tilingX and tilingY.
// 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((width * tilingX),
(height * tilingY),
0.0f);
// Convert from uv space back to pixel space
AZ::Vector3 pixelLookup = (uvw * tiledDimensions);
// 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.
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
y = (height - 1) - y;
return AZ::RPI::GetImageDataPixelValue<float>(m_imageData, imageDescriptor, x, y);
}
}
return defaultValue;
}
void ImageGradientComponent::Activate()
{
// This will immediately call OnGradientTransformChanged and initialize m_gradientTransform.
@ -325,8 +380,8 @@ namespace GradientSignal
if (!wasPointRejected)
{
return GetValueFromImageAsset(
m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f);
return GetValueFromImageData(
uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f);
}
}
@ -358,8 +413,8 @@ namespace GradientSignal
if (!wasPointRejected)
{
outValues[index] = GetValueFromImageAsset(
m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f);
outValues[index] = GetValueFromImageData(
uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f);
}
else
{

@ -15,7 +15,6 @@
#include <AzCore/Debug/Profiler.h>
#include <Atom/ImageProcessing/PixelFormats.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <GradientSignal/Util.h>
#include <numeric>
@ -77,57 +76,4 @@ namespace GradientSignal
return true;
}
float GetValueFromImageAsset(AZStd::span<const uint8_t> imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue)
{
if (!imageData.empty())
{
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.
// For clamping states (Clamp to Zero, Clamp to Edge), a uv value of 1 should point to the last pixel.
// We assume here that the code handling sampler states has handled this for us in the clamping cases
// by reducing our uv by a small delta value such that anything that wants the last pixel has a value
// just slightly less than 1.
// Keeping that in mind, we scale our uv from 0-1 to 0-image size inclusive. So a 4-pixel image will scale
// uv values of 0-1 to 0-4, not 0-3 as you might expect. This is because we want the following range mappings:
// [0 - 1/4) = pixel 0
// [1/4 - 1/2) = pixel 1
// [1/2 - 3/4) = pixel 2
// [3/4 - 1) = pixel 3
// [1 - 1 1/4) = pixel 0
// ...
// Also, based on our tiling settings, we extend the size of our image virtually by a factor of tilingX and tilingY.
// 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((width * tilingX),
(height * tilingY),
0.0f);
// Convert from uv space back to pixel space
AZ::Vector3 pixelLookup = (uvw * tiledDimensions);
// 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.
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
y = (height - 1) - y;
return AZ::RPI::GetImageDataPixelValue<float>(imageData, imageDescriptor, x, y);
}
}
return defaultValue;
}
}

Loading…
Cancel
Save