More GetValues() overrides (#6896)
* Benchmarks and tests for Image and Constant GetValues Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Verify GetValues for Perlin and Random Gradients Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Standardized the assert format for GetValues(). Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * More GetValues unit tests and test cleanup Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed typos Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * GetValues() unit tests for surface gradients. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Benchmarks for ShapeAreaFalloff Gradient Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added benchmarks for all remaining gradients and cleaned up the helper methods. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Renamed class for better report formatting. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added missing Mocks dependencies for the Editor tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * First batch of specific GetValues() overrides. Each one is measurably faster than the generic version. Also, in ShapeAreaFalloffGradient, I optimized and simplified the logic a bit, so GetValue() is marginally faster too. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Change GetValues() to use span and add more overrides. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Convert GetValues() to use AZStd::span and added more overrides. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add missing include. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * PR feedback - switch to fill Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed the logic and added unit tests and comments. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com>
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#include <GradientSignal/Components/ConstantGradientComponent.h>
|
||||
#include <GradientSignal/Components/DitherGradientComponent.h>
|
||||
#include <GradientSignal/Components/InvertGradientComponent.h>
|
||||
@@ -81,6 +83,130 @@ namespace UnitTest
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_CrossingZero)
|
||||
{
|
||||
// With a 4x4 gradient filled with 8/16 (0.5), verify that the resulting dithered output
|
||||
// is an expected checkerboard pattern with 8 of 16 pixels filled. The pattern offset is
|
||||
// shifted -2 in the X direction so that the lookups go from [-2, 2) to verify that the
|
||||
// pattern remains consistent across negative and positive coordinates.
|
||||
|
||||
constexpr int dataSize = 4;
|
||||
|
||||
AZStd::vector<float> inputData(dataSize * dataSize, 8.0f / 16.0f);
|
||||
AZStd::vector<float> expectedOutput = {
|
||||
1.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 1.0f,
|
||||
1.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
auto entityMock = CreateEntity();
|
||||
const AZ::EntityId id = entityMock->GetId();
|
||||
UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize);
|
||||
|
||||
GradientSignal::DitherGradientConfig config;
|
||||
config.m_useSystemPointsPerUnit = false;
|
||||
config.m_pointsPerUnit = 1.0f;
|
||||
config.m_patternOffset = AZ::Vector3(-2.0f, 0.0f, 0.0f);
|
||||
config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4;
|
||||
config.m_gradientSampler.m_gradientId = entityMock->GetId();
|
||||
|
||||
auto entity = CreateEntity();
|
||||
entity->CreateComponent<GradientSignal::DitherGradientComponent>(config);
|
||||
ActivateEntity(entity.get());
|
||||
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_MorePointsPerUnit)
|
||||
{
|
||||
// With a 4x4 gradient filled with 8/16 (0.5), and 1/2 point per unit, if we query a 4x4 region,
|
||||
// we should get a checkerboard in 2x2 blocks of the same value because it takes 2 units before the value changes.
|
||||
|
||||
constexpr int dataSize = 4;
|
||||
|
||||
AZStd::vector<float> inputData(dataSize * dataSize, 8.0f / 16.0f);
|
||||
AZStd::vector<float> expectedOutput = {
|
||||
1.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
auto entityMock = CreateEntity();
|
||||
const AZ::EntityId id = entityMock->GetId();
|
||||
UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize);
|
||||
|
||||
GradientSignal::DitherGradientConfig config;
|
||||
config.m_useSystemPointsPerUnit = false;
|
||||
config.m_pointsPerUnit = 0.5f;
|
||||
config.m_patternOffset = AZ::Vector3::CreateZero();
|
||||
config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4;
|
||||
config.m_gradientSampler.m_gradientId = entityMock->GetId();
|
||||
|
||||
auto entity = CreateEntity();
|
||||
entity->CreateComponent<GradientSignal::DitherGradientComponent>(config);
|
||||
ActivateEntity(entity.get());
|
||||
|
||||
TestFixedDataSampler(expectedOutput, dataSize, entity->GetId());
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_MorePointsAndCrossingZero)
|
||||
{
|
||||
// With a 4x4 gradient filled with 8/16 (0.5), and 2 points per unit, verify that querying
|
||||
// from -1 to 1 produces a constant checkerboard pattern of results as it crosses the 0 boundary.
|
||||
// Our expected results are a consistent checkerboard pattern, but with 2x2 blocks of the same value because we're
|
||||
// querying at 2x the point density (i.e. querying 4 points per unit) to ensure that fractional position lookups work too.
|
||||
|
||||
float expectedValues[] = {
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
// Create a 50% constant gradient.
|
||||
GradientSignal::ConstantGradientConfig constantConfig;
|
||||
constantConfig.m_value = 8.0f / 16.0f;
|
||||
auto constantGradientEntity = CreateEntity();
|
||||
constantGradientEntity->CreateComponent<GradientSignal::ConstantGradientComponent>(constantConfig);
|
||||
ActivateEntity(constantGradientEntity.get());
|
||||
|
||||
GradientSignal::DitherGradientConfig config;
|
||||
config.m_useSystemPointsPerUnit = false;
|
||||
config.m_pointsPerUnit = 2.0f;
|
||||
config.m_patternOffset = AZ::Vector3::CreateZero();
|
||||
config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4;
|
||||
config.m_gradientSampler.m_gradientId = constantGradientEntity->GetId();
|
||||
|
||||
auto entity = CreateEntity();
|
||||
entity->CreateComponent<GradientSignal::DitherGradientComponent>(config);
|
||||
ActivateEntity(entity.get());
|
||||
|
||||
// Run through [-1, 1) at 1/4 intervals and make sure we get our expected checkerboard. This is testing both that
|
||||
// we have a consistent pattern across the 0 boundary and that fractional position lookups work correctly
|
||||
GradientSignal::GradientSampler gradientSampler;
|
||||
gradientSampler.m_gradientId = entity->GetId();
|
||||
int expectedValueIndex = 0;
|
||||
for (float y = -1.0f; y < 1.0f; y += 0.25f)
|
||||
{
|
||||
for (float x = -1.0f; x < 1.0f; x += 0.25f)
|
||||
{
|
||||
GradientSignal::GradientSampleParams params;
|
||||
params.m_position = AZ::Vector3(x, y, 0.0f);
|
||||
|
||||
float actualValue = gradientSampler.GetValue(params);
|
||||
float expectedValue = expectedValues[expectedValueIndex++];
|
||||
|
||||
EXPECT_NEAR(actualValue, expectedValue, 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At31Pct)
|
||||
{
|
||||
// With a 4x4 gradient filled with 5/16 (0.3125), verify that the resulting dithered output
|
||||
|
||||
Reference in New Issue
Block a user