/* * 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 #include #include #include // Using ebus as a temporary workaround #include #include namespace AZ { namespace Render { void PostProcessFeatureProcessor::Reflect(ReflectContext* context) { if (auto* serializeContext = azrtti_cast(context)) { serializeContext ->Class() ->Version(0); } } void PostProcessFeatureProcessor::Activate() { m_currentTime = AZStd::chrono::system_clock::now(); } void PostProcessFeatureProcessor::Deactivate() { m_viewAliasMap.clear(); } void PostProcessFeatureProcessor::UpdateTime() { AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now(); AZStd::chrono::duration deltaTime = now - m_currentTime; m_currentTime = now; m_deltaTime = deltaTime.count(); } void PostProcessFeatureProcessor::SetViewAlias(const AZ::RPI::ViewPtr sourceView, const AZ::RPI::ViewPtr targetView) { m_viewAliasMap[sourceView.get()] = targetView.get(); } void PostProcessFeatureProcessor::RemoveViewAlias(const AZ::RPI::ViewPtr sourceView) { m_viewAliasMap.erase(sourceView.get()); } 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(this); m_blendedPerViewSettings.clear(); // Apply settings from priority sorted list of level settings AZStd::vector_set 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( 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& 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(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) { // check for view aliases first auto viewAliasiterator = m_viewAliasMap.find(view.get()); // Use the view alias if it exists auto settingsIterator = m_blendedPerViewSettings.find(viewAliasiterator != m_viewAliasMap.end() ? viewAliasiterator->second : view.get()); // If no settings for the view is found, the global settings is returned. return settingsIterator != m_blendedPerViewSettings.end() ? &settingsIterator->second : m_globalAggregateLevelSettings.get(); } } // namespace Render } // namespace AZ