Exposed fields to the mesh component giving greater Lod control from the editor

Signed-off-by: Kyle B <kylebirnbaum@gmail.com>
This commit is contained in:
Kyle B
2021-08-02 13:36:10 -07:00
parent c9b3ed8bc7
commit 5b88d96eec
10 changed files with 167 additions and 7 deletions
@@ -63,8 +63,12 @@ namespace AZ
void SetRayTracingData();
void SetSortKey(RHI::DrawItemSortKey sortKey);
RHI::DrawItemSortKey GetSortKey();
void SetLodOverride(RPI::Cullable::LodOverride lodOverride);
void SetLodOverride( RPI::Cullable::LodOverride lodOverride);
RPI::Cullable::LodOverride GetLodOverride();
void SetMinimumScreenCoverage(float minimumScreenCoverage);
float GetMinimumScreenCoverage();
void SetQualityDecayRate(float qualityDecayRate);
float GetQualityDecayRate();
void UpdateDrawPackets(bool forceUpdate = false);
void BuildCullable();
void UpdateCullBounds(const TransformServiceFeatureProcessor* transformService);
@@ -158,6 +162,12 @@ namespace AZ
void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) override;
RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) override;
void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) override;
float GetMinimumScreenCoverage(const MeshHandle& meshHandle) override;
void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) override;
float GetQualityDecayRate(const MeshHandle& meshHandle) override;
void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) override;
void SetRayTracingEnabled(const MeshHandle& meshHandle, bool rayTracingEnabled) override;
void SetVisible(const MeshHandle& meshHandle, bool visible) override;
@@ -98,6 +98,13 @@ namespace AZ
virtual void SetLodOverride(const MeshHandle& meshHandle, RPI::Cullable::LodOverride lodOverride) = 0;
//! Gets the LOD override for a given mesh handle.
virtual RPI::Cullable::LodOverride GetLodOverride(const MeshHandle& meshHandle) = 0;
virtual void SetMinimumScreenCoverage(const MeshHandle& meshHandle, float minimumScreenCoverage) = 0;
virtual float GetMinimumScreenCoverage(const MeshHandle& meshHandle) = 0;
virtual void SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate) = 0;
virtual float GetQualityDecayRate(const MeshHandle& meshHandle) = 0;
//! Sets the option to exclude this mesh from baked reflection probe cubemaps
virtual void SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps) = 0;
//! Sets the option to exclude this mesh from raytracing
@@ -380,6 +380,48 @@ namespace AZ
}
}
void MeshFeatureProcessor::SetMinimumScreenCoverage( const MeshHandle& meshHandle, float minimumScreenCoverage)
{
if (meshHandle.IsValid())
{
meshHandle->SetMinimumScreenCoverage(minimumScreenCoverage);
}
}
float MeshFeatureProcessor::GetMinimumScreenCoverage(const MeshHandle& meshHandle)
{
if (meshHandle.IsValid())
{
return meshHandle->GetMinimumScreenCoverage();
}
else
{
AZ_Assert(false, "Invalid mesh handle");
return 0;
}
}
void MeshFeatureProcessor::SetQualityDecayRate(const MeshHandle& meshHandle, float qualityDecayRate)
{
if (meshHandle.IsValid())
{
meshHandle->SetQualityDecayRate(qualityDecayRate);
}
}
float MeshFeatureProcessor::GetQualityDecayRate(const MeshHandle& meshHandle)
{
if (meshHandle.IsValid())
{
return meshHandle->GetQualityDecayRate();
}
else
{
AZ_Assert(false, "Invalid mesh handle");
return 0;
}
}
void MeshFeatureProcessor::SetExcludeFromReflectionCubeMaps(const MeshHandle& meshHandle, bool excludeFromReflectionCubeMaps)
{
if (meshHandle.IsValid())
@@ -1001,6 +1043,26 @@ namespace AZ
return m_cullable.m_lodData.m_lodOverride;
}
void MeshDataInstance::SetMinimumScreenCoverage(float minimumScreenCoverage)
{
m_cullable.m_lodData.m_minimumScreenCoverage = minimumScreenCoverage;
}
float MeshDataInstance::GetMinimumScreenCoverage()
{
return m_cullable.m_lodData.m_minimumScreenCoverage;
}
void MeshDataInstance::SetQualityDecayRate(float qualityDecayRate)
{
m_cullable.m_lodData.m_qualityDecayRate = qualityDecayRate;
}
float MeshDataInstance::GetQualityDecayRate()
{
return m_cullable.m_lodData.m_qualityDecayRate;
}
void MeshDataInstance::UpdateDrawPackets(bool forceUpdate /*= false*/)
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
@@ -1036,13 +1098,11 @@ namespace AZ
cullData.m_drawListMask.reset();
const size_t lodCount = lodAssets.size();
for (size_t lodIndex = 0; lodIndex < lodCount; ++lodIndex)
{
//initialize the lod
RPI::Cullable::LodData::Lod& lod = lodData.m_lods[lodIndex];
//[GFX TODO][ATOM-5562] - Level of detail: override lod distances and add global lod multiplier(s)
static const float MinimumScreenCoverage = 1.0f/1080.0f; //mesh should cover at least a screen pixel at 1080p to be drawn
static const float ReductionFactor = 0.5f;
if (lodIndex == 0)
{
//first lod
@@ -1051,17 +1111,19 @@ namespace AZ
else
{
//every other lod: use the previous lod's min
lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex-1].m_screenCoverageMin, MinimumScreenCoverage);
lod.m_screenCoverageMax = AZStd::GetMax(lodData.m_lods[lodIndex - 1].m_screenCoverageMin, lodData.m_minimumScreenCoverage);
}
if (lodIndex < lodAssets.size() - 1)
{
//first and middle lods: compute a stepdown value for the min
lod.m_screenCoverageMin = AZStd::GetMax(ReductionFactor * lod.m_screenCoverageMax, MinimumScreenCoverage);
lod.m_screenCoverageMin =
AZStd::GetMax(lodData.m_qualityDecayRate * lod.m_screenCoverageMax, lodData.m_minimumScreenCoverage);
}
else
{
//last lod: use MinimumScreenCoverage for the min
lod.m_screenCoverageMin = MinimumScreenCoverage;
lod.m_screenCoverageMin = lodData.m_minimumScreenCoverage;
}
lod.m_drawPackets.clear();
@@ -88,6 +88,11 @@ namespace AZ
//! Suggest setting to: 0.5f*localAabb.GetExtents().GetMaxElement()
float m_lodSelectionRadius = 1.0f;
// the minimum possibe area a sphere enclosing a mesh projected onto the screen should have before it is culled.
float m_minimumScreenCoverage = 1.0f / 1080.0f;
// The screen area decay between 0 and 1, i.e. closer to 1 -> lose quality immediately, closer to 0 -> never lose quality
float m_qualityDecayRate = 0.5f;
LodOverride m_lodOverride = NoLodOverride;
};
LodData m_lodData;
@@ -39,6 +39,12 @@ namespace AZ
virtual void SetLodOverride(RPI::Cullable::LodOverride lodOverride) = 0;
virtual RPI::Cullable::LodOverride GetLodOverride() const = 0;
virtual void SetMinimumScreenCoverage(float minimumScreenCoverage) = 0;
virtual float GetMinimumScreenCoverage() const = 0;
virtual void SetQualityDecayRate(float qualityDecayRate) = 0;
virtual float GetQualityDecayRate() const = 0;
virtual void SetVisibility(bool visible) = 0;
virtual bool GetVisibility() const = 0;
@@ -76,6 +76,13 @@ namespace AZ
->DataElement(AZ::Edit::UIHandlers::ComboBox, &MeshComponentConfig::m_lodOverride, "Lod Override", "Allows the rendered LOD to be overridden instead of being calculated automatically.")
->Attribute(AZ::Edit::Attributes::EnumValues, &MeshComponentConfig::GetLodOverrideValues)
->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet)
->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_minimumScreenCoverage, "Minimum Screen Coverage", "Minimum proportion of screen area an entitiy takes up, after that the entitiy is culled.")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->Attribute(AZ::Edit::Attributes::Max, 1.f)
->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_qualityDecayRate, "Quality Decay Rate",
"Rate at which mesh quality decays (0 -> always stay highest quality, 1 -> quality falls off to lowest quality immediately).")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->Attribute(AZ::Edit::Attributes::Max, 1.f)
->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_excludeFromReflectionCubeMaps, "Exclude from reflection cubemaps", "Mesh will not be visible in baked reflection probe cubemaps")
->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_useForwardPassIblSpecular, "Use Forward Pass IBL Specular",
@@ -40,6 +40,8 @@ namespace AZ
->Field("ModelAsset", &MeshComponentConfig::m_modelAsset)
->Field("SortKey", &MeshComponentConfig::m_sortKey)
->Field("LodOverride", &MeshComponentConfig::m_lodOverride)
->Field("MinimumScreenCoverage", &MeshComponentConfig::m_minimumScreenCoverage)
->Field("QualityDecayRate", &MeshComponentConfig::m_qualityDecayRate)
->Field("ExcludeFromReflectionCubeMaps", &MeshComponentConfig::m_excludeFromReflectionCubeMaps)
->Field("UseForwardPassIBLSpecular", &MeshComponentConfig::m_useForwardPassIblSpecular);
}
@@ -116,10 +118,16 @@ namespace AZ
->Event("GetSortKey", &MeshComponentRequestBus::Events::GetSortKey)
->Event("SetLodOverride", &MeshComponentRequestBus::Events::SetLodOverride)
->Event("GetLodOverride", &MeshComponentRequestBus::Events::GetLodOverride)
->Event("SetMinimumScreenCoverage", &MeshComponentRequestBus::Events::SetMinimumScreenCoverage)
->Event("GetMinimumScreenCoverage", &MeshComponentRequestBus::Events::GetMinimumScreenCoverage)
->Event("SetQualityDecayRate", &MeshComponentRequestBus::Events::SetQualityDecayRate)
->Event("GetQualityDecayRate", &MeshComponentRequestBus::Events::GetQualityDecayRate)
->VirtualProperty("ModelAssetId", "GetModelAssetId", "SetModelAssetId")
->VirtualProperty("ModelAssetPath", "GetModelAssetPath", "SetModelAssetPath")
->VirtualProperty("SortKey", "GetSortKey", "SetSortKey")
->VirtualProperty("LodOverride", "GetLodOverride", "SetLodOverride")
->VirtualProperty("MinimumScreenCoverage", "GetMinimumScreenCoverage", "SetMinimumScreenCoverage")
->VirtualProperty("QualityDecayRate", "GetQualityDecayRate", "SetQualityDecayRate")
;
}
}
@@ -325,6 +333,8 @@ namespace AZ
m_meshFeatureProcessor->SetTransform(m_meshHandle, transform, m_cachedNonUniformScale);
m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey);
m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride);
m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, m_configuration.m_minimumScreenCoverage);
m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, m_configuration.m_qualityDecayRate);
m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps);
m_meshFeatureProcessor->SetVisible(m_meshHandle, m_isVisible);
@@ -426,6 +436,28 @@ namespace AZ
return m_meshFeatureProcessor->GetSortKey(m_meshHandle);
}
void MeshComponentController::SetMinimumScreenCoverage(float minimumScreenCoverage)
{
m_configuration.m_minimumScreenCoverage = minimumScreenCoverage;
m_meshFeatureProcessor->SetMinimumScreenCoverage(m_meshHandle, minimumScreenCoverage);
}
float MeshComponentController::GetMinimumScreenCoverage() const
{
return m_meshFeatureProcessor->GetMinimumScreenCoverage(m_meshHandle);
}
void MeshComponentController::SetQualityDecayRate(float qualityDecayRate)
{
m_configuration.m_qualityDecayRate = qualityDecayRate;
m_meshFeatureProcessor->SetQualityDecayRate(m_meshHandle, qualityDecayRate);
}
float MeshComponentController::GetQualityDecayRate() const
{
return m_meshFeatureProcessor->GetQualityDecayRate(m_meshHandle);
}
void MeshComponentController::SetVisibility(bool visible)
{
if (m_isVisible != visible)
@@ -46,6 +46,8 @@ namespace AZ
Data::Asset<RPI::ModelAsset> m_modelAsset = { AZ::Data::AssetLoadBehavior::QueueLoad };
RHI::DrawItemSortKey m_sortKey = 0;
RPI::Cullable::LodOverride m_lodOverride = RPI::Cullable::NoLodOverride;
float m_minimumScreenCoverage = 1.0f / 1080.0f;
float m_qualityDecayRate = 0.5f;
bool m_excludeFromReflectionCubeMaps = false;
bool m_useForwardPassIblSpecular = false;
};
@@ -97,6 +99,11 @@ namespace AZ
void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override;
RPI::Cullable::LodOverride GetLodOverride() const override;
void SetMinimumScreenCoverage(float minimumScreenCoverage) override;
float GetMinimumScreenCoverage() const override;
void SetQualityDecayRate(float qualityDecayRate) override;
float GetQualityDecayRate() const override;
void SetVisibility(bool visible) override;
bool GetVisibility() const override;
@@ -415,6 +415,26 @@ namespace AZ
return m_meshFeatureProcessor->GetLodOverride(*m_meshHandle);
}
void AtomActorInstance::SetMinimumScreenCoverage(float minimumScreenCoverage)
{
m_meshFeatureProcessor->SetMinimumScreenCoverage(*m_meshHandle, minimumScreenCoverage);
}
float AtomActorInstance::GetMinimumScreenCoverage() const
{
return m_meshFeatureProcessor->GetMinimumScreenCoverage(*m_meshHandle);
}
void AtomActorInstance::SetQualityDecayRate(float qualityDecayRate)
{
m_meshFeatureProcessor->SetQualityDecayRate(*m_meshHandle, qualityDecayRate);
}
float AtomActorInstance::GetQualityDecayRate() const
{
return m_meshFeatureProcessor->GetQualityDecayRate(*m_meshHandle);
}
void AtomActorInstance::SetVisibility(bool visible)
{
SetIsVisible(visible);
@@ -140,6 +140,10 @@ namespace AZ
RHI::DrawItemSortKey GetSortKey() const override;
void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override;
RPI::Cullable::LodOverride GetLodOverride() const override;
void SetMinimumScreenCoverage(float minimumScreenCoverage) override;
float GetMinimumScreenCoverage() const override;
void SetQualityDecayRate(float qualityDecayRate) override;
float GetQualityDecayRate() const override;
void SetVisibility(bool visible) override;
bool GetVisibility() const override;
// GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler