Merge remote-tracking branch 'upstream/development' into michabr/lyshine_shader_loc

This commit is contained in:
abrmich
2022-01-04 11:33:30 -08:00
98 changed files with 1709 additions and 220 deletions
@@ -10,6 +10,7 @@
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include <Atom/RPI/Math.azsli>
#include "Shadow.azsli"
#include "ShadowmapAtlasLib.azsli"
#include "BicubicPcfFilters.azsli"
@@ -25,6 +26,10 @@
enum class ShadowFilterMethod {None, Pcf, Esm, EsmPcf};
option ShadowFilterMethod o_directional_shadow_filtering_method = ShadowFilterMethod::None;
option bool o_directional_shadow_receiver_plane_bias_enable = true;
option bool o_blend_between_cascades_enable = false;
static const float CascadeBlendArea = 0.015f; // might be worth exposing this as a slider.
// DirectionalLightShadow calculates lit ratio for a directional light.
class DirectionalLightShadow
@@ -98,6 +103,8 @@ class DirectionalLightShadow
float SamplePcfBicubic(float3 shadowCoord, uint indexOfCascade);
float CalculateCascadeBlendAmount(const float3 texCoord);
uint m_lightIndex;
float3 m_shadowCoords[ViewSrg::MaxCascadeCount];
float m_slopeBias[ViewSrg::MaxCascadeCount];
@@ -174,6 +181,7 @@ bool2 DirectionalLightShadow::IsShadowed(float3 shadowCoord, uint indexOfCascade
const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount;
Texture2DArray<float> shadowmap = PassSrg::m_directionalLightShadowmap;
[branch]
if (shadowCoord.x >= 0. && shadowCoord.x * size < size - PixelMargin &&
shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin)
{
@@ -213,20 +221,46 @@ float DirectionalLightShadow::GetVisibilityFromLightPcf()
static const float PixelMargin = 1.5; // avoiding artifact between cascade levels.
static const float DepthMargin = 1e-8; // avoiding artifact when near depth bounds.
bool cascadeFound = false;
int currentCascadeIndex = 0;
const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize;
const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount;
for (uint indexOfCascade = 0; indexOfCascade < cascadeCount; ++indexOfCascade)
{
const float3 shadowCoord = m_shadowCoords[indexOfCascade];
if (shadowCoord.x >= 0. && shadowCoord.x * size < size - PixelMargin &&
shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin &&
shadowCoord.z < 1. - DepthMargin)
{
m_debugInfo.m_cascadeIndex = indexOfCascade;
return SamplePcfBicubic(shadowCoord, indexOfCascade);
currentCascadeIndex = m_debugInfo.m_cascadeIndex = indexOfCascade;
cascadeFound = true;
break;
}
}
[branch]
if (cascadeFound)
{
float lit = SamplePcfBicubic(m_shadowCoords[currentCascadeIndex], currentCascadeIndex);
if(o_blend_between_cascades_enable)
{
const float blendBetweenCascadesAmount = CalculateCascadeBlendAmount(m_shadowCoords[currentCascadeIndex].xyz);
const int nextCascadeIndex = currentCascadeIndex + 1;
[branch]
if (blendBetweenCascadesAmount < 1.0f && nextCascadeIndex < cascadeCount)
{
const float nextLit = SamplePcfBicubic(m_shadowCoords[nextCascadeIndex], nextCascadeIndex);
lit = lerp(nextLit, lit, blendBetweenCascadesAmount);
}
}
return lit;
}
m_debugInfo.m_cascadeIndex = cascadeCount;
return 1.;
}
@@ -244,6 +278,8 @@ float DirectionalLightShadow::GetVisibilityFromLightEsm()
const float distanceMin = ViewSrg::m_esmsDirectional[indexOfCascade].m_lightDistanceOfCameraViewFrustum;
bool2 checkedShadowed = IsShadowed(shadowCoord, indexOfCascade);
const float depthDiff = shadowCoord.z - distanceMin;
[branch]
if (checkedShadowed.x && depthDiff >= 0)
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
@@ -274,6 +310,8 @@ float DirectionalLightShadow::GetVisibilityFromLightEsmPcf()
const float distanceMin = ViewSrg::m_esmsDirectional[indexOfCascade].m_lightDistanceOfCameraViewFrustum;
bool2 checkedShadowed = IsShadowed(shadowCoord, indexOfCascade);
const float depthDiff = shadowCoord.z - distanceMin;
[branch]
if (checkedShadowed.x && depthDiff >= 0)
{
const float distanceWithinCameraView = depthDiff / (1. - distanceMin);
@@ -319,6 +357,7 @@ float DirectionalLightShadow::SamplePcfBicubic(float3 shadowCoord, uint indexOfC
param.samplerState = SceneSrg::m_hwPcfSampler;
param.receiverPlaneDepthBias = o_directional_shadow_receiver_plane_bias_enable ? ComputeReceiverPlaneDepthBias(m_shadowPosDX[indexOfCascade], m_shadowPosDY[indexOfCascade]) : 0;
[branch]
if (filteringSampleCount <= 4)
{
return SampleShadowMapBicubic_4Tap(param);
@@ -420,3 +459,10 @@ float3 DirectionalLightShadow::AddDebugColoring(
}
return color;
}
float DirectionalLightShadow::CalculateCascadeBlendAmount(const float3 texCoord)
{
const float distanceToOneMin = min3(1.0f - texCoord);
const float currentPixelsBlendBandLocation = min(min(texCoord.x, texCoord.y), distanceToOneMin);
return currentPixelsBlendBandLocation / CascadeBlendArea;
}
@@ -368,16 +368,19 @@ void CullDecals(uint groupIndex, TileLightData tileLightData, float3 aabb_center
float3 decalPosition = WorldToView_Point(decal.m_position);
// just wrapping a bounding sphere around a cube for now to get a minor perf boost. i.e. the sphere radius is sqrt(x*x + y*y + z*z)
// ATOM-4224 - try AABB-AABB and implement depth binning for the decals
float maxHalfSize = max(max(decal.m_halfSize.x, decal.m_halfSize.y), decal.m_halfSize.z);
float boundingSphereRadiusSqr = maxHalfSize * maxHalfSize * 3;
// ATOM-4224 - try AABB-AABB
float boundingSphereRadiusSqr = dot(decal.m_halfSize, decal.m_halfSize);
bool potentiallyIntersects = TestSphereVsAabb(decalPosition, boundingSphereRadiusSqr, aabb_center, aabb_extents);
if (potentiallyIntersects)
{
// Implement and profile fine-grained light culling testing
// ATOM-3732
MarkLightAsVisibleInSharedMemory(decalIndex, 0xFFFF);
uint inside = 0;
float2 minmax = ComputePointLightMinMaxZ(sqrt(boundingSphereRadiusSqr), decalPosition);
if (IsObjectInsideTile(tileLightData, minmax, inside))
{
MarkLightAsVisibleInSharedMemory(decalIndex, inside);
}
}
}
}
@@ -163,6 +163,9 @@ namespace AZ
//! Reduces acne by biasing the shadowmap lookup along the geometric normal.
virtual void SetNormalShadowBias(LightHandle handle, float normalShadowBias) = 0;
//! Sets whether or not blending between shadow map cascades is enabled.
virtual void SetCascadeBlendingEnabled(LightHandle handle, bool enable) = 0;
};
} // namespace Render
} // namespace AZ
@@ -198,13 +198,15 @@ namespace AZ
if (m_shadowingLightHandle.IsValid())
{
uint32_t shadowFilterMethod = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_shadowFilterMethod;
const uint32_t shadowFilterMethod = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_shadowFilterMethod;
RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowFilteringMethodName, AZ::RPI::ShaderOptionValue{shadowFilterMethod});
RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowReceiverPlaneBiasEnableName, AZ::RPI::ShaderOptionValue{ m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()).m_isReceiverPlaneBiasEnabled });
RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowReceiverPlaneBiasEnableName, AZ::RPI::ShaderOptionValue{ m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()).m_isReceiverPlaneBiasEnabled });
const uint32_t cascadeCount = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_cascadeCount;
ShadowProperty& property = m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex());
RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_BlendBetweenCascadesEnableName, AZ::RPI::ShaderOptionValue{cascadeCount > 1 && m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()).m_blendBetwenCascades });
ShadowProperty& property = m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex());
bool segmentsNeedUpdate = property.m_segments.empty();
for (const auto& passIt : m_cascadedShadowmapsPasses)
{
@@ -577,6 +579,11 @@ namespace AZ
m_shadowProperties.GetData(handle.GetIndex()).m_isReceiverPlaneBiasEnabled = enable;
}
void DirectionalLightFeatureProcessor::SetCascadeBlendingEnabled(LightHandle handle, bool enable)
{
m_shadowProperties.GetData(handle.GetIndex()).m_blendBetwenCascades = enable;
}
void DirectionalLightFeatureProcessor::SetShadowBias(LightHandle handle, float bias)
{
for (auto& it : m_shadowData)
@@ -176,6 +176,8 @@ namespace AZ
// If true, this will reduce the shadow acne introduced by large pcf kernels by estimating the angle of the triangle being shaded
// with the ddx/ddy functions.
bool m_isReceiverPlaneBiasEnabled = true;
bool m_blendBetwenCascades = false;
};
static void Reflect(ReflectContext* context);
@@ -215,6 +217,7 @@ namespace AZ
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override;
void SetCascadeBlendingEnabled(LightHandle handle, bool enable) override;
void SetShadowBias(LightHandle handle, float bias) override;
void SetNormalShadowBias(LightHandle handle, float normalShadowBias) override;
@@ -367,6 +370,7 @@ namespace AZ
Name m_lightTypeName = Name("directional");
Name m_directionalShadowFilteringMethodName = Name("o_directional_shadow_filtering_method");
Name m_directionalShadowReceiverPlaneBiasEnableName = Name("o_directional_shadow_receiver_plane_bias_enable");
Name m_BlendBetweenCascadesEnableName = Name("o_blend_between_cascades_enable");
static constexpr const char* FeatureProcessorName = "DirectionalLightFeatureProcessor";
};
} // namespace Render
@@ -9,6 +9,7 @@
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/string/conversions.h>
@@ -184,6 +184,14 @@ namespace AZ
//! Reduces acne by biasing the shadowmap lookup along the geometric normal.
//! @param normalShadowBias Sets the amount of normal shadow bias to apply.
virtual void SetNormalShadowBias(float normalShadowBias) = 0;
//! Gets whether the directional shadow map has cascade blending enabled.
//! This smooths out the border between cascades at the cost of some performance in the blend area.
virtual bool GetCascadeBlendingEnabled() const = 0;
//! Sets whether the directional shadow map has cascade blending enabled.
//! @param enable flag specifying whether to enable cascade blending.
virtual void SetCascadeBlendingEnabled(bool enable) = 0;
};
using DirectionalLightRequestBus = EBus<DirectionalLightRequests>;
@@ -115,6 +115,9 @@ namespace AZ
//! Reduces shadow acne by applying a small amount of offset along shadow-space z.
float m_shadowBias = 0.0f;
// If true, sample between two adjacent shadow map cascades in a small boundary area to smooth out the transition.
bool m_cascadeBlendingEnabled = false;
bool IsSplitManual() const;
bool IsSplitAutomatic() const;
bool IsCascadeCorrectionDisabled() const;
@@ -40,7 +40,8 @@ namespace AZ
->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount)
->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled)
->Field("Shadow Bias", &DirectionalLightComponentConfig::m_shadowBias)
->Field("Normal Shadow Bias", &DirectionalLightComponentConfig::m_normalShadowBias);
->Field("Normal Shadow Bias", &DirectionalLightComponentConfig::m_normalShadowBias)
->Field("CascadeBlendingEnabled", &DirectionalLightComponentConfig::m_cascadeBlendingEnabled);
}
}
@@ -113,8 +114,7 @@ namespace AZ
bool DirectionalLightComponentConfig::IsShadowPcfDisabled() const
{
return !(m_shadowFilterMethod == ShadowFilterMethod::Pcf ||
m_shadowFilterMethod == ShadowFilterMethod::EsmPcf);
return !(m_shadowFilterMethod == ShadowFilterMethod::Pcf);
}
bool DirectionalLightComponentConfig::IsEsmDisabled() const
@@ -88,6 +88,8 @@ namespace AZ
->Event("SetShadowBias", &DirectionalLightRequestBus::Events::SetShadowBias)
->Event("GetNormalShadowBias", &DirectionalLightRequestBus::Events::GetNormalShadowBias)
->Event("SetNormalShadowBias", &DirectionalLightRequestBus::Events::SetNormalShadowBias)
->Event("GetCascadeBlendingEnabled", &DirectionalLightRequestBus::Events::GetCascadeBlendingEnabled)
->Event("SetCascadeBlendingEnabled", &DirectionalLightRequestBus::Events::SetCascadeBlendingEnabled)
->VirtualProperty("Color", "GetColor", "SetColor")
->VirtualProperty("Intensity", "GetIntensity", "SetIntensity")
->VirtualProperty("AngularDiameter", "GetAngularDiameter", "SetAngularDiameter")
@@ -104,7 +106,8 @@ namespace AZ
->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount")
->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled")
->VirtualProperty("ShadowBias", "GetShadowBias", "SetShadowBias")
->VirtualProperty("NormalShadowBias", "GetNormalShadowBias", "SetNormalShadowBias");
->VirtualProperty("NormalShadowBias", "GetNormalShadowBias", "SetNormalShadowBias")
->VirtualProperty("BlendBetweenCascadesEnabled", "GetCascadeBlendingEnabled", "SetCascadeBlendingEnabled");
;
}
}
@@ -537,6 +540,7 @@ namespace AZ
SetNormalShadowBias(m_configuration.m_normalShadowBias);
SetFilteringSampleCount(m_configuration.m_filteringSampleCount);
SetShadowReceiverPlaneBiasEnabled(m_configuration.m_receiverPlaneBiasEnabled);
SetCascadeBlendingEnabled(m_configuration.m_cascadeBlendingEnabled);
// [GFX TODO][ATOM-1726] share config for multiple light (e.g., light ID).
// [GFX TODO][ATOM-2416] adapt to multiple viewports.
@@ -636,5 +640,16 @@ namespace AZ
m_featureProcessor->SetShadowReceiverPlaneBiasEnabled(m_lightHandle, enable);
}
bool DirectionalLightComponentController::GetCascadeBlendingEnabled() const
{
return m_configuration.m_cascadeBlendingEnabled;
}
void DirectionalLightComponentController::SetCascadeBlendingEnabled(bool enable)
{
m_configuration.m_cascadeBlendingEnabled = enable;
m_featureProcessor->SetCascadeBlendingEnabled(m_lightHandle, enable);
}
} // namespace Render
} // namespace AZ
@@ -83,7 +83,9 @@ namespace AZ
float GetShadowBias() const override;
void SetShadowBias(float bias) override;
float GetNormalShadowBias() const override;
void SetNormalShadowBias(float bias) override;
void SetNormalShadowBias(float bias) override;
bool GetCascadeBlendingEnabled() const override;
void SetCascadeBlendingEnabled(bool enable) override;
private:
friend class EditorDirectionalLightComponent;
@@ -161,7 +161,11 @@ namespace AZ
->Attribute(Edit::Attributes::Min, 0.f)
->Attribute(Edit::Attributes::Max, 10.0f)
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
;
->DataElement(
Edit::UIHandlers::CheckBox, &DirectionalLightComponentConfig::m_cascadeBlendingEnabled,
"Blend between cascades\n", "Enables smooth blending between shadow map cascades.")
->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled)
;
}
}
@@ -688,7 +688,7 @@ namespace MCommon
const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(jointIndex).m_position;
const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
const AZ::Vector3 bone = parentWorldPos - nodeWorldPos;
const AZ::Vector3 boneDirection = MCore::SafeNormalize(bone);
const AZ::Vector3 boneDirection = bone.GetNormalizedSafe();
const float boneLength = MCore::SafeLength(bone);
const float boneScale = GetBoneScale(actorInstance, joint);
const float parentBoneScale = GetBoneScale(actorInstance, skeleton->GetNode(parentIndex));
@@ -258,9 +258,9 @@ namespace EMotionFX
// Calculate the matrix to rotate the solve plane.
void BlendTreeFootIKNode::CalculateMatrix(const AZ::Vector3& goal, const AZ::Vector3& bendDir, AZ::Matrix3x3* outForward)
{
const AZ::Vector3 x = MCore::SafeNormalize(goal);
const AZ::Vector3 x = goal.GetNormalizedSafe();
const float dot = bendDir.Dot(x);
const AZ::Vector3 y = MCore::SafeNormalize(bendDir - (dot * x));
const AZ::Vector3 y = (bendDir - (dot * x)).GetNormalizedSafe();
const AZ::Vector3 z = x.Cross(y);
outForward->SetRow(0, x);
outForward->SetRow(1, y);
@@ -189,11 +189,11 @@ namespace EMotionFX
void BlendTreeTwoLinkIKNode::CalculateMatrix(const AZ::Vector3& goal, const AZ::Vector3& bendDir, AZ::Matrix3x3* outForward)
{
// the inverse matrix defines a coordinate system whose x axis contains P, so X = unit(P).
const AZ::Vector3 x = MCore::SafeNormalize(goal);
const AZ::Vector3 x = goal.GetNormalizedSafe();
// the y axis of the inverse is perpendicular to P, so Y = unit( D - X(D . X) ).
const float dot = bendDir.Dot(x);
const AZ::Vector3 y = MCore::SafeNormalize(bendDir - (dot * x));
const AZ::Vector3 y = (bendDir - (dot * x)).GetNormalizedSafe();
// the z axis of the inverse is perpendicular to both X and Y, so Z = X x Y.
const AZ::Vector3 z = x.Cross(y);
@@ -372,11 +372,11 @@ namespace EMotionFX
if (m_relativeBendDir && !m_extractBendDir)
{
bendDir = actorInstance->GetWorldSpaceTransform().m_rotation.TransformVector(bendDir);
bendDir = MCore::SafeNormalize(bendDir);
bendDir.NormalizeSafe();
}
else
{
bendDir = MCore::SafeNormalize(bendDir);
bendDir.NormalizeSafe();
}
// if end node rotation is enabled
@@ -470,8 +470,8 @@ namespace EMotionFX
// calculate the differences between the current forward vector and the new one after IK
AZ::Vector3 oldForward = globalTransformB.m_position - globalTransformA.m_position;
AZ::Vector3 newForward = midPos - globalTransformA.m_position;
oldForward = MCore::SafeNormalize(oldForward);
newForward = MCore::SafeNormalize(newForward);
oldForward.NormalizeSafe();
newForward.NormalizeSafe();
// perform a delta rotation to rotate into the new direction after IK
float dotProduct = oldForward.Dot(newForward);
@@ -499,9 +499,8 @@ namespace EMotionFX
oldForward = endEffectorNodePos - globalTransformB.m_position;
}
oldForward = MCore::SafeNormalize(oldForward);
newForward = goal - globalTransformB.m_position;
newForward = MCore::SafeNormalize(newForward);
oldForward.NormalizeSafe();
newForward = (goal - globalTransformB.m_position).GetNormalizedSafe();
// calculate the delta rotation
dotProduct = oldForward.Dot(newForward);
@@ -581,8 +581,8 @@ namespace EMotionFX
&curTangent, &curBitangent);
// normalize the vectors
curTangent = MCore::SafeNormalize(curTangent);
curBitangent = MCore::SafeNormalize(curBitangent);
curTangent.NormalizeSafe();
curBitangent.NormalizeSafe();
// store the tangents in the orgTangents array
const AZ::Vector4 vec4Tangent(curTangent.GetX(), curTangent.GetY(), curTangent.GetZ(), 1.0f);
@@ -605,7 +605,7 @@ namespace EMotionFX
{
// get the normal
AZ::Vector3 normal(normals[i]);
normal = MCore::SafeNormalize(normal);
normal.NormalizeSafe();
// get the tangent
AZ::Vector3 tangent = AZ::Vector3(orgTangents[i].GetX(), orgTangents[i].GetY(), orgTangents[i].GetZ());
@@ -631,7 +631,7 @@ namespace EMotionFX
// Gram-Schmidt orthogonalize
AZ::Vector3 fixedTangent = tangent - (normal * normal.Dot(tangent));
fixedTangent = MCore::SafeNormalize(fixedTangent);
fixedTangent.NormalizeSafe();
// calculate handedness
const AZ::Vector3 crossResult = normal.Cross(tangent);
@@ -1671,7 +1671,7 @@ namespace EMotionFX
const AZ::Vector3& posA = positions[ indexA ];
const AZ::Vector3& posB = positions[ indexB ];
const AZ::Vector3& posC = positions[ indexC ];
AZ::Vector3 faceNormal = MCore::SafeNormalize((posB - posA).Cross(posC - posB));
AZ::Vector3 faceNormal = (posB - posA).Cross(posC - posB).GetNormalizedSafe();
// store the tangents in the orgTangents array
smoothNormals[ orgVerts[indexA] ] += faceNormal;
@@ -1684,7 +1684,7 @@ namespace EMotionFX
// normalize
for (uint32 i = 0; i < m_numOrgVerts; ++i)
{
smoothNormals[i] = MCore::SafeNormalize(smoothNormals[i]);
smoothNormals[i].NormalizeSafe();
}
for (uint32 i = 0; i < m_numVertices; ++i)
@@ -1721,7 +1721,7 @@ namespace EMotionFX
const AZ::Vector3& posA = positions[ indexA ];
const AZ::Vector3& posB = positions[ indexB ];
const AZ::Vector3& posC = positions[ indexC ];
AZ::Vector3 faceNormal = MCore::SafeNormalize((posB - posA).Cross(posC - posB));
AZ::Vector3 faceNormal = (posB - posA).Cross(posC - posB).GetNormalizedSafe();
// store the tangents in the orgTangents array
normals[indexA] = normals[indexA] + faceNormal;
@@ -1734,7 +1734,7 @@ namespace EMotionFX
// normalize the normals
for (uint32 i = 0; i < m_numVertices; ++i)
{
normals[i] = MCore::SafeNormalize(normals[i]);
normals[i].NormalizeSafe();
}
}
}
@@ -0,0 +1,83 @@
/*
* 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 <EMotionFX/Source/Velocity.h>
#include <AzCore/Math/MathUtils.h>
namespace EMotionFX
{
AZ::Vector3 CalculateLinearVelocity(const AZ::Vector3& lastPosition,
const AZ::Vector3& currentPosition,
float timeDelta)
{
if (timeDelta <= AZ::Constants::FloatEpsilon)
{
return AZ::Vector3::CreateZero();
}
const AZ::Vector3 deltaPosition = currentPosition - lastPosition;
const AZ::Vector3 velocity = deltaPosition / timeDelta;
if (velocity.GetLength() > AZ::Constants::FloatEpsilon)
{
return velocity;
}
return AZ::Vector3::CreateZero();
}
AZ::Vector3 CalculateAngularVelocity(const AZ::Quaternion& lastRotation,
const AZ::Quaternion& currentRotation,
float timeDelta)
{
if (timeDelta <= AZ::Constants::FloatEpsilon)
{
return AZ::Vector3::CreateZero();
}
const AZ::Quaternion deltaRotation = currentRotation * lastRotation.GetInverseFull();
const AZ::Quaternion shortestEquivalent = deltaRotation.GetShortestEquivalent().GetNormalized();
const AZ::Vector3 scaledAxisAngle = shortestEquivalent.ConvertToScaledAxisAngle();
const AZ::Vector3 angularVelocity = scaledAxisAngle / timeDelta;
if (angularVelocity.GetLength() > AZ::Constants::FloatEpsilon)
{
return angularVelocity;
}
return AZ::Vector3::CreateZero();
}
void DebugDrawVelocity(AzFramework::DebugDisplayRequests& debugDisplay,
const AZ::Vector3& position, const AZ::Vector3& velocity, const AZ::Color& color)
{
// Don't visualize joints that remain motionless (zero velocity).
if (velocity.GetLength() < AZ::Constants::FloatEpsilon)
{
return;
}
const float scale = 0.15f;
const AZ::Vector3 arrowPosition = position + velocity;
debugDisplay.DepthTestOff();
debugDisplay.SetColor(color);
debugDisplay.DrawSolidCylinder(/*center=*/(arrowPosition + position) * 0.5f,
/*direction=*/(arrowPosition - position).GetNormalizedSafe(),
/*radius=*/0.003f,
/*height=*/(arrowPosition - position).GetLength(),
/*drawShaded=*/false);
debugDisplay.DrawSolidCone(position + velocity,
velocity,
0.1f * scale,
scale * 0.5f,
/*drawShaded=*/false);
}
} // namespace EMotionFX
@@ -0,0 +1,23 @@
/*
* 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
*
*/
#pragma once
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Quaternion.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <EMotionFX/Source/EMotionFXConfig.h>
namespace EMotionFX
{
AZ::Vector3 EMFX_API CalculateLinearVelocity(const AZ::Vector3& lastPosition, const AZ::Vector3& currentPosition, float timeDelta);
AZ::Vector3 EMFX_API CalculateAngularVelocity(const AZ::Quaternion& lastRotation, const AZ::Quaternion& currentRotation, float timeDelta);
void EMFX_API DebugDrawVelocity(AzFramework::DebugDisplayRequests& debugDisplay,
const AZ::Vector3& position, const AZ::Vector3& velocity, const AZ::Color& color);
} // namespace EMotionFX
@@ -144,6 +144,8 @@ set(FILES
Source/TransformData.h
Source/TriggerActionSetup.cpp
Source/TriggerActionSetup.h
Source/Velocity.cpp
Source/Velocity.h
Source/VertexAttributeLayer.cpp
Source/VertexAttributeLayer.h
Source/VertexAttributeLayerAbstractData.cpp
@@ -17,12 +17,14 @@
namespace MCore
{
//! @deprecated Use AZ::Vector3::NormalizeSafeWithLength()
inline float SafeLength(const AZ::Vector3& rhs)
{
const float lenSq = rhs.Dot(rhs);
return (lenSq > FLT_EPSILON) ? sqrtf(lenSq) : 0.0f;
}
//! @deprecated Use AZ::Vector3::GetNormalizedSafe()
inline AZ::Vector3 SafeNormalize(const AZ::Vector3& rhs)
{
AZ::Vector3 result(0.0f);
@@ -43,6 +45,7 @@ namespace MCore
return AZ::Vector3(vec.GetX() - fac * n.GetX(), vec.GetY() - fac * n.GetY(), vec.GetZ() - fac * n.GetZ());
}
//! @deprecated Use AZ::Vector3::Project()
MCORE_INLINE AZ::Vector3 Projected(const AZ::Vector3& vec, const AZ::Vector3& projectOnto)
{
AZ::Vector3 result = projectOnto;
@@ -60,6 +63,7 @@ namespace MCore
(MCore::Math::Abs(val.GetX() - val.GetZ()) < MCore::Math::epsilon));
}
//! @deprecated Use AZ::Vector3::Lerp()
template <>
MCORE_INLINE AZ::Vector3 LinearInterpolate(const AZ::Vector3& source, const AZ::Vector3& target, float timeValue)
{
@@ -6,7 +6,7 @@
*
*/
#include "ConstantGradientComponent.h"
#include <GradientSignal/Components/ConstantGradientComponent.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "DitherGradientComponent.h"
#include <GradientSignal/Components/DitherGradientComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "GradientSurfaceDataComponent.h"
#include <GradientSignal/Components/GradientSurfaceDataComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "GradientTransformComponent.h"
#include <GradientSignal/Components/GradientTransformComponent.h>
#include <AzCore/Math/Vector2.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "ImageGradientComponent.h"
#include <GradientSignal/Components/ImageGradientComponent.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Debug/Profiler.h>
@@ -6,7 +6,7 @@
*
*/
#include "InvertGradientComponent.h"
#include <GradientSignal/Components/InvertGradientComponent.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "LevelsGradientComponent.h"
#include <GradientSignal/Components/LevelsGradientComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "MixedGradientComponent.h"
#include <GradientSignal/Components/MixedGradientComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "PerlinGradientComponent.h"
#include <GradientSignal/Components/PerlinGradientComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Jobs/Job.h>
#include <AzCore/Jobs/JobFunction.h>
@@ -6,7 +6,7 @@
*
*/
#include "PosterizeGradientComponent.h"
#include <GradientSignal/Components/PosterizeGradientComponent.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "RandomGradientComponent.h"
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "ReferenceGradientComponent.h"
#include <GradientSignal/Components/ReferenceGradientComponent.h>
#include <AzCore/Debug/Profiler.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "ShapeAreaFalloffGradientComponent.h"
#include <GradientSignal/Components/ShapeAreaFalloffGradientComponent.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "SmoothStepGradientComponent.h"
#include <GradientSignal/Components/SmoothStepGradientComponent.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "SurfaceAltitudeGradientComponent.h"
#include <GradientSignal/Components/SurfaceAltitudeGradientComponent.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "SurfaceMaskGradientComponent.h"
#include <GradientSignal/Components/SurfaceMaskGradientComponent.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "SurfaceSlopeGradientComponent.h"
#include <GradientSignal/Components/SurfaceSlopeGradientComponent.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
@@ -6,7 +6,7 @@
*
*/
#include "ThresholdGradientComponent.h"
#include <GradientSignal/Components/ThresholdGradientComponent.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/ConstantGradientComponent.h>
#include <GradientSignal/Components/ConstantGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/DitherGradientComponent.h>
#include <GradientSignal/Components/DitherGradientComponent.h>
namespace GradientSignal
{
@@ -8,7 +8,7 @@
#pragma once
#include <Components/GradientSurfaceDataComponent.h>
#include <GradientSignal/Components/GradientSurfaceDataComponent.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
@@ -8,7 +8,7 @@
#pragma once
#include <Components/GradientTransformComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
namespace GradientSignal
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/ImageGradientComponent.h>
#include <GradientSignal/Components/ImageGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/InvertGradientComponent.h>
#include <GradientSignal/Components/InvertGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/LevelsGradientComponent.h>
#include <GradientSignal/Components/LevelsGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/MixedGradientComponent.h>
#include <GradientSignal/Components/MixedGradientComponent.h>
namespace GradientSignal
{
@@ -10,7 +10,7 @@
#include <AzCore/Module/Module.h>
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/PerlinGradientComponent.h>
#include <GradientSignal/Components/PerlinGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/PosterizeGradientComponent.h>
#include <GradientSignal/Components/PosterizeGradientComponent.h>
namespace GradientSignal
{
@@ -12,7 +12,7 @@
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <GradientSignal/Editor/EditorGradientTypeIds.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
#include <Components/RandomGradientComponent.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/ReferenceGradientComponent.h>
#include <GradientSignal/Components/ReferenceGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/ShapeAreaFalloffGradientComponent.h>
#include <GradientSignal/Components/ShapeAreaFalloffGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/SmoothStepGradientComponent.h>
#include <GradientSignal/Components/SmoothStepGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/SurfaceAltitudeGradientComponent.h>
#include <GradientSignal/Components/SurfaceAltitudeGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/SurfaceMaskGradientComponent.h>
#include <GradientSignal/Components/SurfaceMaskGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/SurfaceSlopeGradientComponent.h>
#include <GradientSignal/Components/SurfaceSlopeGradientComponent.h>
namespace GradientSignal
{
@@ -9,7 +9,7 @@
#pragma once
#include <GradientSignal/Editor/EditorGradientComponentBase.h>
#include <Components/ThresholdGradientComponent.h>
#include <GradientSignal/Components/ThresholdGradientComponent.h>
namespace GradientSignal
{
@@ -9,24 +9,24 @@
#include <GradientSignalModule.h>
#include <GradientSignalSystemComponent.h>
#include <Components/SmoothStepGradientComponent.h>
#include <Components/SurfaceAltitudeGradientComponent.h>
#include <Components/SurfaceSlopeGradientComponent.h>
#include <Components/MixedGradientComponent.h>
#include <Components/ImageGradientComponent.h>
#include <Components/ConstantGradientComponent.h>
#include <Components/ThresholdGradientComponent.h>
#include <Components/LevelsGradientComponent.h>
#include <Components/ReferenceGradientComponent.h>
#include <Components/InvertGradientComponent.h>
#include <Components/DitherGradientComponent.h>
#include <Components/PosterizeGradientComponent.h>
#include <Components/ShapeAreaFalloffGradientComponent.h>
#include <Components/PerlinGradientComponent.h>
#include <Components/RandomGradientComponent.h>
#include <Components/GradientTransformComponent.h>
#include <Components/SurfaceMaskGradientComponent.h>
#include <Components/GradientSurfaceDataComponent.h>
#include <GradientSignal/Components/SmoothStepGradientComponent.h>
#include <GradientSignal/Components/SurfaceAltitudeGradientComponent.h>
#include <GradientSignal/Components/SurfaceSlopeGradientComponent.h>
#include <GradientSignal/Components/MixedGradientComponent.h>
#include <GradientSignal/Components/ImageGradientComponent.h>
#include <GradientSignal/Components/ConstantGradientComponent.h>
#include <GradientSignal/Components/ThresholdGradientComponent.h>
#include <GradientSignal/Components/LevelsGradientComponent.h>
#include <GradientSignal/Components/ReferenceGradientComponent.h>
#include <GradientSignal/Components/InvertGradientComponent.h>
#include <GradientSignal/Components/DitherGradientComponent.h>
#include <GradientSignal/Components/PosterizeGradientComponent.h>
#include <GradientSignal/Components/ShapeAreaFalloffGradientComponent.h>
#include <GradientSignal/Components/PerlinGradientComponent.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
#include <GradientSignal/Components/SurfaceMaskGradientComponent.h>
#include <GradientSignal/Components/GradientSurfaceDataComponent.h>
namespace GradientSignal
{
@@ -16,10 +16,10 @@
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <Source/Components/ImageGradientComponent.h>
#include <Source/Components/PerlinGradientComponent.h>
#include <Source/Components/RandomGradientComponent.h>
#include <Source/Components/GradientTransformComponent.h>
#include <GradientSignal/Components/ImageGradientComponent.h>
#include <GradientSignal/Components/PerlinGradientComponent.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
namespace UnitTest
{
@@ -15,8 +15,8 @@
#include <AzCore/Math/Vector2.h>
#include <AzFramework/Asset/AssetCatalogBus.h>
#include <Source/Components/ImageGradientComponent.h>
#include <Source/Components/GradientTransformComponent.h>
#include <GradientSignal/Components/ImageGradientComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
namespace UnitTest
{
@@ -12,16 +12,16 @@
#include <AzCore/Math/MathUtils.h>
#include <Tests/GradientSignalTestFixtures.h>
#include <Source/Components/MixedGradientComponent.h>
#include <Source/Components/ReferenceGradientComponent.h>
#include <Source/Components/ShapeAreaFalloffGradientComponent.h>
#include <Source/Components/SurfaceAltitudeGradientComponent.h>
#include <Source/Components/SurfaceMaskGradientComponent.h>
#include <Source/Components/SurfaceSlopeGradientComponent.h>
#include <Source/Components/RandomGradientComponent.h>
#include <Source/Components/ConstantGradientComponent.h>
#include <Source/Components/DitherGradientComponent.h>
#include <Components/ImageGradientComponent.h>
#include <GradientSignal/Components/MixedGradientComponent.h>
#include <GradientSignal/Components/ReferenceGradientComponent.h>
#include <GradientSignal/Components/ShapeAreaFalloffGradientComponent.h>
#include <GradientSignal/Components/SurfaceAltitudeGradientComponent.h>
#include <GradientSignal/Components/SurfaceMaskGradientComponent.h>
#include <GradientSignal/Components/SurfaceSlopeGradientComponent.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <GradientSignal/Components/ConstantGradientComponent.h>
#include <GradientSignal/Components/DitherGradientComponent.h>
#include <GradientSignal/Components/ImageGradientComponent.h>
namespace UnitTest
{
@@ -10,9 +10,9 @@
#include <AzTest/AzTest.h>
#include <Source/Components/ConstantGradientComponent.h>
#include <Source/Components/DitherGradientComponent.h>
#include <Source/Components/InvertGradientComponent.h>
#include <GradientSignal/Components/ConstantGradientComponent.h>
#include <GradientSignal/Components/DitherGradientComponent.h>
#include <GradientSignal/Components/InvertGradientComponent.h>
namespace UnitTest
{
@@ -11,8 +11,8 @@
#include <AzCore/Math/MathUtils.h>
#include <Tests/GradientSignalTestFixtures.h>
#include <Source/Components/ConstantGradientComponent.h>
#include <Source/Components/GradientSurfaceDataComponent.h>
#include <GradientSignal/Components/ConstantGradientComponent.h>
#include <GradientSignal/Components/GradientSurfaceDataComponent.h>
namespace UnitTest
{
@@ -11,13 +11,13 @@
#include <GradientSignal/PerlinImprovedNoise.h>
#include <GradientSignal/Ebuses/GradientRequestBus.h>
#include <Source/Components/PerlinGradientComponent.h>
#include <Source/Components/RandomGradientComponent.h>
#include <Source/Components/LevelsGradientComponent.h>
#include <Source/Components/PosterizeGradientComponent.h>
#include <Source/Components/SmoothStepGradientComponent.h>
#include <Source/Components/ThresholdGradientComponent.h>
#include <Source/Components/GradientTransformComponent.h>
#include <GradientSignal/Components/PerlinGradientComponent.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <GradientSignal/Components/LevelsGradientComponent.h>
#include <GradientSignal/Components/PosterizeGradientComponent.h>
#include <GradientSignal/Components/SmoothStepGradientComponent.h>
#include <GradientSignal/Components/ThresholdGradientComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
namespace UnitTest
{
@@ -15,7 +15,7 @@
#include <AzCore/Math/Vector2.h>
#include <AZTestShared/Math/MathTestHelpers.h>
#include <Source/Components/GradientTransformComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
namespace UnitTest
{
@@ -15,6 +15,24 @@ set(FILES
Include/GradientSignal/PerlinImprovedNoise.h
Include/GradientSignal/Util.h
Include/GradientSignal/GradientImageConversion.h
Include/GradientSignal/Components/ConstantGradientComponent.h
Include/GradientSignal/Components/DitherGradientComponent.h
Include/GradientSignal/Components/GradientSurfaceDataComponent.h
Include/GradientSignal/Components/GradientTransformComponent.h
Include/GradientSignal/Components/ImageGradientComponent.h
Include/GradientSignal/Components/InvertGradientComponent.h
Include/GradientSignal/Components/LevelsGradientComponent.h
Include/GradientSignal/Components/MixedGradientComponent.h
Include/GradientSignal/Components/PerlinGradientComponent.h
Include/GradientSignal/Components/PosterizeGradientComponent.h
Include/GradientSignal/Components/RandomGradientComponent.h
Include/GradientSignal/Components/ReferenceGradientComponent.h
Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h
Include/GradientSignal/Components/SmoothStepGradientComponent.h
Include/GradientSignal/Components/SurfaceAltitudeGradientComponent.h
Include/GradientSignal/Components/SurfaceMaskGradientComponent.h
Include/GradientSignal/Components/SurfaceSlopeGradientComponent.h
Include/GradientSignal/Components/ThresholdGradientComponent.h
Include/GradientSignal/Ebuses/GradientTransformRequestBus.h
Include/GradientSignal/Ebuses/GradientRequestBus.h
Include/GradientSignal/Ebuses/GradientPreviewRequestBus.h
@@ -40,41 +58,23 @@ set(FILES
Include/GradientSignal/Ebuses/GradientSurfaceDataRequestBus.h
Include/GradientSignal/Ebuses/SmoothStepRequestBus.h
Source/Components/ConstantGradientComponent.cpp
Source/Components/ConstantGradientComponent.h
Source/Components/DitherGradientComponent.cpp
Source/Components/DitherGradientComponent.h
Source/Components/GradientSurfaceDataComponent.cpp
Source/Components/GradientSurfaceDataComponent.h
Source/Components/GradientTransformComponent.cpp
Source/Components/GradientTransformComponent.h
Source/Components/ImageGradientComponent.cpp
Source/Components/ImageGradientComponent.h
Source/Components/InvertGradientComponent.cpp
Source/Components/InvertGradientComponent.h
Source/Components/LevelsGradientComponent.cpp
Source/Components/LevelsGradientComponent.h
Source/Components/MixedGradientComponent.cpp
Source/Components/MixedGradientComponent.h
Source/Components/PerlinGradientComponent.cpp
Source/Components/PerlinGradientComponent.h
Source/Components/PosterizeGradientComponent.cpp
Source/Components/PosterizeGradientComponent.h
Source/Components/RandomGradientComponent.cpp
Source/Components/RandomGradientComponent.h
Source/Components/ReferenceGradientComponent.cpp
Source/Components/ReferenceGradientComponent.h
Source/Components/ShapeAreaFalloffGradientComponent.cpp
Source/Components/ShapeAreaFalloffGradientComponent.h
Source/Components/SmoothStepGradientComponent.cpp
Source/Components/SmoothStepGradientComponent.h
Source/Components/SurfaceAltitudeGradientComponent.cpp
Source/Components/SurfaceAltitudeGradientComponent.h
Source/Components/SurfaceMaskGradientComponent.cpp
Source/Components/SurfaceMaskGradientComponent.h
Source/Components/SurfaceSlopeGradientComponent.cpp
Source/Components/SurfaceSlopeGradientComponent.h
Source/Components/ThresholdGradientComponent.cpp
Source/Components/ThresholdGradientComponent.h
Source/GradientSampler.cpp
Source/GradientSignalSystemComponent.cpp
Source/GradientSignalSystemComponent.h
+6
View File
@@ -159,6 +159,12 @@ namespace PhysX
AZStd::swap(m_entityTransformHandlers[index], m_entityTransformHandlers.back());
m_entityTransformHandlers.pop_back();
// When deleting entity from handler's m_entities, the AABB should be appended to m_pendingAabbUpdates
// for local wind handler to broadcast OnWindChanged to notify relative entities of wind changes in OnTick().
m_pendingAabbUpdates.push_back();
ColliderShapeRequestBus::EventResult(m_pendingAabbUpdates.back(),
entityId, &ColliderShapeRequestBus::Events::GetColliderShapeAabb);
m_changed = true;
}
}
+5
View File
@@ -119,6 +119,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
NAME Gem::Terrain.Tests
)
ly_add_googlebenchmark(
NAME Gem::Terrain.Benchmarks
TARGET Gem::Terrain.Tests
)
# If we are a host platform we want to add tools test like editor tests here
if(PAL_TRAIT_BUILD_HOST_TOOLS)
# We support Terrain.Editor.Tests on this platform, add Terrain.Editor.Tests target which depends on Terrain.Editor
@@ -32,6 +32,13 @@ namespace Terrain
AZ_RTTI(TerrainSurfaceGradientMapping, "{473AD2CE-F22A-45A9-803F-2192F3D9F2BF}");
static void Reflect(AZ::ReflectContext* context);
TerrainSurfaceGradientMapping() = default;
TerrainSurfaceGradientMapping(const AZ::EntityId& entityId, const SurfaceData::SurfaceTag& surfaceTag)
: m_gradientEntityId(entityId)
, m_surfaceTag(surfaceTag)
{
}
AZ::EntityId m_gradientEntityId;
SurfaceData::SurfaceTag m_surfaceTag;
};
@@ -0,0 +1,421 @@
/*
* 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
*
*/
#ifdef HAVE_BENCHMARK
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
#include <AzTest/AzTest.h>
#include <GradientSignal/Components/RandomGradientComponent.h>
#include <GradientSignal/Components/GradientTransformComponent.h>
#include <GradientSignal/Ebuses/GradientRequestBus.h>
#include <SurfaceData/SurfaceDataTypes.h>
#include <LmbrCentral/Shape/ShapeComponentBus.h>
#include <MockAxisAlignedBoxShapeComponent.h>
#include <TerrainSystem/TerrainSystem.h>
#include <Components/TerrainLayerSpawnerComponent.h>
#include <Components/TerrainHeightGradientListComponent.h>
#include <Components/TerrainSurfaceGradientListComponent.h>
#include <benchmark/benchmark.h>
namespace UnitTest
{
using ::testing::NiceMock;
using ::testing::Return;
class TerrainSystemBenchmarkFixture
: public UnitTest::AllocatorsBenchmarkFixture
, public UnitTest::TraceBusRedirector
{
public:
void SetUp(const benchmark::State& state) override
{
InternalSetUp(state);
}
void SetUp(benchmark::State& state) override
{
InternalSetUp(state);
}
void TearDown(const benchmark::State& state) override
{
InternalTearDown(state);
}
void TearDown(benchmark::State& state) override
{
InternalTearDown(state);
}
void InternalSetUp(const benchmark::State& state)
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
UnitTest::AllocatorsBenchmarkFixture::SetUp(state);
m_app = AZStd::make_unique<AZ::ComponentApplication>();
ASSERT_TRUE(m_app != nullptr);
AZ::ComponentApplication::Descriptor componentAppDesc;
AZ::Entity* systemEntity = m_app->Create(componentAppDesc);
ASSERT_TRUE(systemEntity != nullptr);
m_app->AddEntity(systemEntity);
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
}
void InternalTearDown(const benchmark::State& state)
{
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
m_app->Destroy();
m_app.reset();
UnitTest::AllocatorsBenchmarkFixture::TearDown(state);
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
AZStd::unique_ptr<AZ::Entity> CreateEntity()
{
return AZStd::make_unique<AZ::Entity>();
}
void ActivateEntity(AZ::Entity* entity)
{
entity->Init();
entity->Activate();
}
template<typename Component, typename Configuration>
Component* CreateComponent(AZ::Entity* entity, const Configuration& config)
{
m_app->RegisterComponentDescriptor(Component::CreateDescriptor());
return entity->CreateComponent<Component>(config);
}
template<typename Component>
Component* CreateComponent(AZ::Entity* entity)
{
m_app->RegisterComponentDescriptor(Component::CreateDescriptor());
return entity->CreateComponent<Component>();
}
// Create a terrain system with reasonable defaults for testing, but with the ability to override the defaults
// on a test-by-test basis.
AZStd::unique_ptr<Terrain::TerrainSystem> CreateAndActivateTerrainSystem(
AZ::Vector2 queryResolution = AZ::Vector2(1.0f),
AZ::Aabb worldBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-128.0f), AZ::Vector3(128.0f)))
{
// Create the terrain system and give it one tick to fully initialize itself.
auto terrainSystem = AZStd::make_unique<Terrain::TerrainSystem>();
terrainSystem->SetTerrainAabb(worldBounds);
terrainSystem->SetTerrainHeightQueryResolution(queryResolution);
terrainSystem->Activate();
AZ::TickBus::Broadcast(&AZ::TickBus::Events::OnTick, 0.f, AZ::ScriptTimePoint{});
return terrainSystem;
}
// Create a mock shape bus listener that will listen to the given EntityId for shape requests and returns the following:
// - GetEncompassingAabb - returns the given Aabb
// - GetTransformAndLocalBounds - returns the center of the Aabb as the transform, and the size of the Aabb as the local bounds
// - IsPointInside - true if the point is in the Aabb, false if not
AZStd::unique_ptr<NiceMock<UnitTest::MockShapeComponentRequests>> CreateMockShape(
const AZ::Aabb& spawnerBox, const AZ::EntityId& shapeEntityId)
{
AZStd::unique_ptr<NiceMock<UnitTest::MockShapeComponentRequests>> mockShape =
AZStd::make_unique<NiceMock<UnitTest::MockShapeComponentRequests>>(shapeEntityId);
ON_CALL(*mockShape, GetEncompassingAabb).WillByDefault(Return(spawnerBox));
ON_CALL(*mockShape, GetTransformAndLocalBounds)
.WillByDefault(
[spawnerBox](AZ::Transform& transform, AZ::Aabb& bounds)
{
transform = AZ::Transform::CreateTranslation(spawnerBox.GetCenter());
bounds = spawnerBox.GetTranslated(-spawnerBox.GetCenter());
});
ON_CALL(*mockShape, IsPointInside)
.WillByDefault(
[spawnerBox](const AZ::Vector3& point) -> bool
{
return spawnerBox.Contains(point);
});
return mockShape;
}
// Create an entity with a Random Gradient on it that can be used for gradient queries.
AZStd::unique_ptr<AZ::Entity> CreateTestRandomGradientEntity(const AZ::Aabb& spawnerBox, uint32_t randomSeed)
{
// Create the base entity
AZStd::unique_ptr<AZ::Entity> testGradientEntity = CreateEntity();
// Add a mock AABB Shape so that the shape requirement is fulfilled.
CreateComponent<UnitTest::MockAxisAlignedBoxShapeComponent>(testGradientEntity.get());
// Create the Random Gradient Component with some default parameters.
GradientSignal::RandomGradientConfig config;
config.m_randomSeed = randomSeed;
CreateComponent<GradientSignal::RandomGradientComponent>(testGradientEntity.get(), config);
// Create the Gradient Transform Component with some default parameters.
GradientSignal::GradientTransformConfig gradientTransformConfig;
gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None;
CreateComponent<GradientSignal::GradientTransformComponent>(testGradientEntity.get(), gradientTransformConfig);
// Set the transform to match the given spawnerBox
auto transform = CreateComponent<AzFramework::TransformComponent>(testGradientEntity.get());
transform->SetLocalTM(AZ::Transform::CreateTranslation(spawnerBox.GetCenter()));
transform->SetWorldTM(AZ::Transform::CreateTranslation(spawnerBox.GetCenter()));
return testGradientEntity;
}
AZStd::unique_ptr<AZ::Entity> CreateTestLayerSpawnerEntity(
const AZ::Aabb& spawnerBox, const AZ::EntityId& heightGradientEntityId,
const Terrain::TerrainSurfaceGradientListConfig& surfaceConfig)
{
// Create the base entity
AZStd::unique_ptr<AZ::Entity> testLayerSpawnerEntity = CreateEntity();
// Add a mock AABB Shape so that the shape requirement is fulfilled.
CreateComponent<UnitTest::MockAxisAlignedBoxShapeComponent>(testLayerSpawnerEntity.get());
// Add a Terrain Layer Spawner
CreateComponent<Terrain::TerrainLayerSpawnerComponent>(testLayerSpawnerEntity.get());
// Add a Terrain Height Gradient List with one entry pointing to the given gradient entity
Terrain::TerrainHeightGradientListConfig heightConfig;
heightConfig.m_gradientEntities.emplace_back(heightGradientEntityId);
CreateComponent<Terrain::TerrainHeightGradientListComponent>(testLayerSpawnerEntity.get(), heightConfig);
// Add a Terrain Surface Gradient List with however many entries we were given
CreateComponent<Terrain::TerrainSurfaceGradientListComponent>(testLayerSpawnerEntity.get(), surfaceConfig);
// Set the transform to match the given spawnerBox
auto transform = CreateComponent<AzFramework::TransformComponent>(testLayerSpawnerEntity.get());
transform->SetLocalTM(AZ::Transform::CreateTranslation(spawnerBox.GetCenter()));
transform->SetWorldTM(AZ::Transform::CreateTranslation(spawnerBox.GetCenter()));
return testLayerSpawnerEntity;
}
void RunTerrainApiBenchmark(
benchmark::State& state,
AZStd::function<void(
const AZ::Vector2& queryResolution,
const AZ::Aabb& worldBounds,
AzFramework::Terrain::TerrainDataRequests::Sampler sampler)> ApiCaller)
{
// Get the ranges for querying from our benchmark parameters
float boundsRange = aznumeric_cast<float>(state.range(0));
uint32_t numSurfaces = aznumeric_cast<uint32_t>(state.range(1));
AzFramework::Terrain::TerrainDataRequests::Sampler sampler =
static_cast<AzFramework::Terrain::TerrainDataRequests::Sampler>(state.range(2));
// Set up our world bounds and query resolution
AZ::Aabb worldBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-boundsRange / 2.0f), AZ::Vector3(boundsRange / 2.0f));
AZ::Vector2 queryResolution = AZ::Vector2(1.0f);
// Create a Random Gradient to use as our height provider
const uint32_t heightRandomSeed = 12345;
auto heightGradientEntity = CreateTestRandomGradientEntity(worldBounds, heightRandomSeed);
auto heightGradientShapeRequests = CreateMockShape(worldBounds, heightGradientEntity->GetId());
ActivateEntity(heightGradientEntity.get());
// Create a set of Random Gradients to use as our surface providers
Terrain::TerrainSurfaceGradientListConfig surfaceConfig;
AZStd::vector<AZStd::unique_ptr<AZ::Entity>> surfaceGradientEntities;
AZStd::vector<AZStd::unique_ptr<NiceMock<UnitTest::MockShapeComponentRequests>>> surfaceGradientShapeRequests;
for (uint32_t surfaces = 0; surfaces < numSurfaces; surfaces++)
{
const uint32_t surfaceRandomSeed = 23456 + surfaces;
auto surfaceGradientEntity = CreateTestRandomGradientEntity(worldBounds, surfaceRandomSeed);
auto shapeRequests = CreateMockShape(worldBounds, surfaceGradientEntity->GetId());
ActivateEntity(surfaceGradientEntity.get());
// Give each gradient a new surface tag
surfaceConfig.m_gradientSurfaceMappings.emplace_back(
surfaceGradientEntity->GetId(), SurfaceData::SurfaceTag(AZStd::string::format("test%u", surfaces)));
surfaceGradientEntities.emplace_back(AZStd::move(surfaceGradientEntity));
surfaceGradientShapeRequests.emplace_back(AZStd::move(shapeRequests));
}
// Create a single Terrain Layer Spawner that covers the entire terrain world bounds
// (Do this *after* creating and activating the height and surface gradients)
auto testLayerSpawnerEntity = CreateTestLayerSpawnerEntity(worldBounds, heightGradientEntity->GetId(), surfaceConfig);
auto spawnerShapeRequests = CreateMockShape(worldBounds, testLayerSpawnerEntity->GetId());
ActivateEntity(testLayerSpawnerEntity.get());
// Create the terrain system (do this after creating the terrain layer entity to ensure that we don't need any data refreshes)
auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution, worldBounds);
// Call the terrain API we're testing for every height and width in our ranges.
for (auto stateIterator : state)
{
ApiCaller(queryResolution, worldBounds, sampler);
}
testLayerSpawnerEntity.reset();
spawnerShapeRequests.reset();
heightGradientEntity.reset();
heightGradientShapeRequests.reset();
surfaceGradientEntities.clear();
surfaceGradientShapeRequests.clear();
}
protected:
AZStd::unique_ptr<AZ::ComponentApplication> m_app;
};
BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetHeight)(benchmark::State& state)
{
// Run the benchmark
RunTerrainApiBenchmark(
state,
[]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds,
AzFramework::Terrain::TerrainDataRequests::Sampler sampler)
{
float worldMinZ = worldBounds.GetMin().GetZ();
for (float y = worldBounds.GetMin().GetY(); y < worldBounds.GetMax().GetY(); y += 1.0f)
{
for (float x = worldBounds.GetMin().GetX(); x < worldBounds.GetMax().GetX(); x += 1.0f)
{
float terrainHeight = worldMinZ;
bool terrainExists = false;
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
terrainHeight, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, sampler, &terrainExists);
benchmark::DoNotOptimize(terrainHeight);
}
}
});
}
BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetHeight)
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 4096, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 4096, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 4096, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Unit(::benchmark::kMillisecond);
BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetNormal)(benchmark::State& state)
{
// Run the benchmark
RunTerrainApiBenchmark(
state,
[]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds,
AzFramework::Terrain::TerrainDataRequests::Sampler sampler)
{
for (float y = worldBounds.GetMin().GetY(); y < worldBounds.GetMax().GetY(); y += 1.0f)
{
for (float x = worldBounds.GetMin().GetX(); x < worldBounds.GetMax().GetX(); x += 1.0f)
{
AZ::Vector3 terrainNormal;
bool terrainExists = false;
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(
terrainNormal, &AzFramework::Terrain::TerrainDataRequests::GetNormalFromFloats, x, y, sampler, &terrainExists);
benchmark::DoNotOptimize(terrainNormal);
}
}
});
}
BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetNormal)
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Unit(::benchmark::kMillisecond);
BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetSurfaceWeights)(benchmark::State& state)
{
// Run the benchmark
RunTerrainApiBenchmark(
state,
[]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds,
AzFramework::Terrain::TerrainDataRequests::Sampler sampler)
{
AzFramework::SurfaceData::SurfaceTagWeightList surfaceWeights;
for (float y = worldBounds.GetMin().GetY(); y < worldBounds.GetMax().GetY(); y += 1.0f)
{
for (float x = worldBounds.GetMin().GetX(); x < worldBounds.GetMax().GetX(); x += 1.0f)
{
bool terrainExists = false;
AzFramework::Terrain::TerrainDataRequestBus::Broadcast(
&AzFramework::Terrain::TerrainDataRequests::GetSurfaceWeightsFromFloats, x, y, surfaceWeights, sampler,
&terrainExists);
benchmark::DoNotOptimize(surfaceWeights);
}
}
});
}
BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetSurfaceWeights)
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 1024, 2, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 2, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 1024, 4, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 4, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Unit(::benchmark::kMillisecond);
BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetSurfacePoints)(benchmark::State& state)
{
// Run the benchmark
RunTerrainApiBenchmark(
state,
[]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds,
AzFramework::Terrain::TerrainDataRequests::Sampler sampler)
{
AzFramework::SurfaceData::SurfacePoint surfacePoint;
for (float y = worldBounds.GetMin().GetY(); y < worldBounds.GetMax().GetY(); y += 1.0f)
{
for (float x = worldBounds.GetMin().GetX(); x < worldBounds.GetMax().GetX(); x += 1.0f)
{
bool terrainExists = false;
AzFramework::Terrain::TerrainDataRequestBus::Broadcast(
&AzFramework::Terrain::TerrainDataRequests::GetSurfacePointFromFloats, x, y, surfacePoint, sampler,
&terrainExists);
benchmark::DoNotOptimize(surfacePoint);
}
}
});
}
BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_GetSurfacePoints)
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) })
->Args({ 1024, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Args({ 2048, 1, static_cast<int>(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) })
->Unit(::benchmark::kMillisecond);
#endif
}
@@ -16,4 +16,5 @@ set(FILES
Tests/TerrainHeightGradientListTests.cpp
Tests/TerrainMacroMaterialTests.cpp
Tests/TerrainSurfaceGradientListTests.cpp
Tests/TerrainSystemBenchmarks.cpp
)