From b2c7cf44520c3b08d2e3815d093b79b971da5d11 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 16 Feb 2022 09:53:06 -0600 Subject: [PATCH] Moved GetValueFromImageAsset from ImageAsset to ImageGradientComponent Signed-off-by: Chris Galvan --- .../Components/ImageGradientComponent.h | 1 + .../Code/Include/GradientSignal/ImageAsset.h | 2 - .../Components/ImageGradientComponent.cpp | 63 +++++++++++++++++-- .../GradientSignal/Code/Source/ImageAsset.cpp | 54 ---------------- 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h index 7ec1c785e5..ca1de2cdc1 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h @@ -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; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h index 500251d924..14920a2370 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h @@ -62,6 +62,4 @@ namespace GradientSignal } }; - float GetValueFromImageAsset(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue); - } // namespace GradientSignal diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index fe4c134ed2..ddbba771d7 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -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(pixelLookup.GetX()) % width; + auto y = aznumeric_cast(pixelLookup.GetY()) % height; + + // Flip the y because images are stored in reverse of our world axes + y = (height - 1) - y; + + return AZ::RPI::GetImageDataPixelValue(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 { diff --git a/Gems/GradientSignal/Code/Source/ImageAsset.cpp b/Gems/GradientSignal/Code/Source/ImageAsset.cpp index 05ad13d193..a8b41df949 100644 --- a/Gems/GradientSignal/Code/Source/ImageAsset.cpp +++ b/Gems/GradientSignal/Code/Source/ImageAsset.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -77,57 +76,4 @@ namespace GradientSignal return true; } - - float GetValueFromImageAsset(AZStd::span 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(pixelLookup.GetX()) % width; - auto y = aznumeric_cast(pixelLookup.GetY()) % height; - - // Flip the y because images are stored in reverse of our world axes - y = (height - 1) - y; - - return AZ::RPI::GetImageDataPixelValue(imageData, imageDescriptor, x, y); - } - } - - return defaultValue; - } }