You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor...

213 lines
7.9 KiB
C++

/*
* 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 <PostProcess/PostProcessFeatureProcessor.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
// Using ebus as a temporary workaround
#include <AzFramework/Components/CameraBus.h>
#include <AzCore/Debug/EventTrace.h>
namespace AZ
{
namespace Render
{
void PostProcessFeatureProcessor::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext
->Class<PostProcessFeatureProcessor, FeatureProcessor>()
->Version(0);
}
}
void PostProcessFeatureProcessor::Activate()
{
m_currentTime = AZStd::chrono::system_clock::now();
}
void PostProcessFeatureProcessor::UpdateTime()
{
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
AZStd::chrono::duration<float> deltaTime = now - m_currentTime;
m_currentTime = now;
m_deltaTime = deltaTime.count();
}
void PostProcessFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet)
{
AZ_PROFILE_SCOPE(RPI, "PostProcessFeatureProcessor: Simulate");
AZ_UNUSED(packet);
UpdateTime();
if (m_settingsChanged)
{
SortPostProcessSettings();
AggregateLevelSettings();
m_settingsChanged = false;
}
// simulate both the global and each view's post process settings
// Ideally, every view should be associated to a post process settings. The global
// setting is returned when a view does not have a post process setting.
// e.g. Editor Camera, AtomSampleViewer Samples that do not set perViewBlendWeights
m_globalAggregateLevelSettings->Simulate(m_deltaTime);
for (auto& settingsPair : m_blendedPerViewSettings)
{
settingsPair.second.Simulate(m_deltaTime);
}
}
void PostProcessFeatureProcessor::SortPostProcessSettings()
{
// Clear settings from previous frame
m_sortedFrameSettings.clear();
// Sort post process settings by layer value and priority
m_sortedFrameSettings.reserve(m_settings.size());
for (auto& settings : m_settings)
{
m_sortedFrameSettings.push_back(settings.m_postProcessSettings.get());
}
AZStd::sort(
m_sortedFrameSettings.begin(),
m_sortedFrameSettings.end(),
[](const PostProcessSettings* lhs, const PostProcessSettings* rhs)-> bool
{
return
AZStd::make_pair(lhs->GetLayerCategoryValue(), lhs->GetPriority()) >
AZStd::make_pair(rhs->GetLayerCategoryValue(), rhs->GetPriority());
}
);
}
void PostProcessFeatureProcessor::AggregateLevelSettings()
{
// Remove outdated level settings aggregate
m_globalAggregateLevelSettings = AZStd::make_unique<PostProcessSettings>(this);
m_blendedPerViewSettings.clear();
// Apply settings from priority sorted list of level settings
AZStd::vector_set<const RPI::View*> activeViews;
for (auto& settings : m_sortedFrameSettings)
{
// Apply settings that are not associated with views
if (settings->m_perViewBlendWeights.empty())
{
settings->ApplySettingsTo(m_globalAggregateLevelSettings.get());
}
// Create a setting for each view
for (auto& viewWeightPair : settings->m_perViewBlendWeights)
{
// create a post process setting if it doesn't exist
AZ::RPI::View* view = viewWeightPair.first;
activeViews.insert(view);
auto viewSettngsIterator = m_blendedPerViewSettings.find(view);
if (viewSettngsIterator == m_blendedPerViewSettings.end())
{
viewSettngsIterator = m_blendedPerViewSettings.insert(
AZStd::pair<AZ::RPI::View*, PostProcessSettings>(
view,
PostProcessSettings(this))).first;
}
// apply settings
float blendWeight = settings->GetBlendWeightForView(viewWeightPair.first);
auto& viewSettings = viewSettngsIterator->second;
settings->ApplySettingsTo(&viewSettings, blendWeight);
}
}
//RemoveOutdatedViewSettings(activeViews);
}
void PostProcessFeatureProcessor::RemoveOutdatedViewSettings(const AZStd::vector_set<const RPI::View*>& activeViews)
{
for (auto perViewSetting = m_blendedPerViewSettings.begin(); perViewSetting != m_blendedPerViewSettings.end(); )
{
if (AZStd::find(activeViews.begin(), activeViews.end(), perViewSetting->first) == activeViews.end())
{
perViewSetting = m_blendedPerViewSettings.erase(perViewSetting);
}
else
{
++perViewSetting;
}
}
}
void PostProcessFeatureProcessor::OnPostProcessSettingsChanged()
{
m_settingsChanged = true;
}
PostProcessSettingsInterface* PostProcessFeatureProcessor::GetSettingsInterface(EntityId entityId)
{
for (EntitySettingsEntry& entry : m_settings)
{
if (entry.m_entityId == entityId)
{
return entry.m_postProcessSettings.get();
}
}
return nullptr;
}
PostProcessSettingsInterface* PostProcessFeatureProcessor::GetOrCreateSettingsInterface(EntityId entityId)
{
// Check for settings already registered with entity ID
PostProcessSettingsInterface* settingsInterface = GetSettingsInterface(entityId);
if (settingsInterface)
{
return settingsInterface;
}
// Create new post process settings
EntitySettingsEntry newEntry;
newEntry.m_entityId = entityId;
newEntry.m_postProcessSettings = AZStd::make_unique<PostProcessSettings>(this);
settingsInterface = newEntry.m_postProcessSettings.get();
m_settings.push_back(AZStd::move(newEntry));
return settingsInterface;
}
void PostProcessFeatureProcessor::RemoveSettingsInterface(EntityId entityId)
{
for (auto iter = m_settings.begin(); iter < m_settings.end(); ++iter)
{
if (iter->m_entityId == entityId)
{
m_settings.erase(iter);
break;
}
}
}
AZ::Render::PostProcessSettings* PostProcessFeatureProcessor::GetLevelSettingsFromView(AZ::RPI::ViewPtr view)
{
// If no settings for the view is found, the global settings is returned.
auto settingsIterator = m_blendedPerViewSettings.find(view.get());
return settingsIterator != m_blendedPerViewSettings.end()
? &settingsIterator->second
: m_globalAggregateLevelSettings.get();
}
} // namespace Render
} // namespace AZ