123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * 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 <Atom/Feature/SkyBox/SkyboxConstants.h>
- #include <SkyBox/HDRiSkyboxComponentController.h>
- #include <AzCore/RTTI/BehaviorContext.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <Atom/RPI.Public/Scene.h>
- #include <Atom/Utils/Utils.h>
- namespace AZ
- {
- namespace Render
- {
- void HDRiSkyboxComponentController::Reflect(ReflectContext* context)
- {
- HDRiSkyboxComponentConfig::Reflect(context);
- if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
- {
- serializeContext->Class<HDRiSkyboxComponentController>()
- ->Version(1)
- ->Field("Configuration", &HDRiSkyboxComponentController::m_configuration);
- }
- if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
- {
- behaviorContext->EBus<HDRiSkyboxRequestBus>("HDRiSkyboxRequestBus")
- ->Event("SetExposure", &HDRiSkyboxRequestBus::Events::SetExposure)
- ->Event("GetExposure", &HDRiSkyboxRequestBus::Events::GetExposure)
- ->VirtualProperty("Exposure", "GetExposure", "SetExposure")
- ->Event("GetCubemapAssetId", &HDRiSkyboxRequestBus::Events::GetCubemapAssetId)
- ->Event("SetCubemapAssetId", &HDRiSkyboxRequestBus::Events::SetCubemapAssetId)
- ->Attribute(AZ::Script::Attributes::AssetType, azrtti_typeid<AZ::RPI::StreamingImageAsset>())
- ->Event("SetCubemapAssetPath", &HDRiSkyboxRequestBus::Events::SetCubemapAssetPath)
- ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::List)
- ->Event("GetCubemapAssetPath", &HDRiSkyboxRequestBus::Events::GetCubemapAssetPath)
- ;
- }
- }
- void HDRiSkyboxComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
- {
- provided.push_back(AZ_CRC_CE("SkyBoxService"));
- }
- void HDRiSkyboxComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
- {
- incompatible.push_back(AZ_CRC_CE("SkyBoxService"));
- incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
- }
- void HDRiSkyboxComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
- {
- required.push_back(AZ_CRC_CE("TransformService"));
- }
- HDRiSkyboxComponentController::HDRiSkyboxComponentController(const HDRiSkyboxComponentConfig& config)
- : m_configuration(config)
- {
- }
- void HDRiSkyboxComponentController::Activate(EntityId entityId)
- {
- m_featureProcessorInterface = RPI::Scene::GetFeatureProcessorForEntity<SkyBoxFeatureProcessorInterface>(entityId);
- // only activate if there is no other skybox activate
- if (m_featureProcessorInterface && !m_featureProcessorInterface->IsEnabled())
- {
- m_featureProcessorInterface->SetSkyboxMode(SkyBoxMode::Cubemap);
- m_featureProcessorInterface->Enable(true);
- m_entityId = entityId;
- SetCubemapAsset(m_configuration.m_cubemapAsset);
- SetExposure(m_configuration.m_exposure);
- m_transformInterface = TransformBus::FindFirstHandler(m_entityId);
- AZ_Assert(m_transformInterface, "Unable to attach to a TransformBus handler. Entity transform will not affect to skybox.");
- const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity();
- m_featureProcessorInterface->SetCubemapRotationMatrix(GetInverseTransform(transform));
- HDRiSkyboxRequestBus::Handler::BusConnect(m_entityId);
- TransformNotificationBus::Handler::BusConnect(m_entityId);
- m_isActive = true;
- }
- else
- {
- m_featureProcessorInterface = nullptr;
- AZ_Warning("HDRiSkyboxComponentController", false, "There is already another HDRi Skybox or Physical Sky component in the scene!");
- }
- }
- void HDRiSkyboxComponentController::Deactivate()
- {
- // Run deactivate if this skybox is activate
- if (m_isActive)
- {
- HDRiSkyboxRequestBus::Handler::BusDisconnect(m_entityId);
- TransformNotificationBus::Handler::BusDisconnect(m_entityId);
- Data::AssetBus::MultiHandler::BusDisconnect();
- m_configuration.m_cubemapAsset.Release();
- m_featureProcessorInterface->Enable(false);
- m_featureProcessorInterface = nullptr;
- m_transformInterface = nullptr;
- m_isActive = false;
- }
- }
- void HDRiSkyboxComponentController::SetConfiguration(const HDRiSkyboxComponentConfig& config)
- {
- m_configuration = config;
- }
- const HDRiSkyboxComponentConfig& HDRiSkyboxComponentController::GetConfiguration() const
- {
- return m_configuration;
- }
- void HDRiSkyboxComponentController::OnAssetReady(Data::Asset<Data::AssetData> asset)
- {
- UpdateWithAsset(asset);
- }
- void HDRiSkyboxComponentController::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
- {
- UpdateWithAsset(asset);
- }
- void HDRiSkyboxComponentController::OnAssetError(Data::Asset<Data::AssetData> asset)
- {
- UpdateWithAsset(asset);
- }
- void HDRiSkyboxComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
- {
- m_featureProcessorInterface->SetCubemapRotationMatrix(GetInverseTransform(world));
- }
- Data::Asset<RPI::StreamingImageAsset> HDRiSkyboxComponentController::GetCubemapAsset() const
- {
- return m_configuration.m_cubemapAsset;
- }
- void HDRiSkyboxComponentController::SetCubemapAsset(const Data::Asset<RPI::StreamingImageAsset>& cubemapAsset)
- {
- Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_cubemapAsset.GetId());
- m_configuration.m_cubemapAsset = cubemapAsset;
- LoadImage(m_configuration.m_cubemapAsset);
- }
- void HDRiSkyboxComponentController::SetCubemapAssetId(AZ::Data::AssetId assetId)
- {
- AZStd::string assetPathString;
- Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &Data::AssetCatalogRequests::GetAssetPathById, assetId);
- SetCubemapAssetPath(assetPathString);
- }
- void HDRiSkyboxComponentController::SetCubemapAssetPath(const AZStd::string& path)
- {
- SetCubemapAsset(GetAssetFromPath<RPI::StreamingImageAsset>(path, m_configuration.m_cubemapAsset.GetAutoLoadBehavior()));
- }
- AZStd::string HDRiSkyboxComponentController::GetCubemapAssetPath() const
- {
- AZStd::string assetPathString;
- Data::AssetCatalogRequestBus::BroadcastResult(assetPathString, &Data::AssetCatalogRequests::GetAssetPathById, m_configuration.m_cubemapAsset.GetId());
- return assetPathString;
- }
- AZ::Data::AssetId HDRiSkyboxComponentController::GetCubemapAssetId() const
- {
- return m_configuration.m_cubemapAsset.GetId();
- }
- void HDRiSkyboxComponentController::SetExposure(float exposure)
- {
- m_configuration.m_exposure = exposure;
- m_featureProcessorInterface->SetCubemapExposure(exposure);
- }
- float HDRiSkyboxComponentController::GetExposure() const
- {
- return m_configuration.m_exposure;
- }
- void HDRiSkyboxComponentController::LoadImage(Data::Asset<RPI::StreamingImageAsset>& imageAsset)
- {
- Data::AssetBus::MultiHandler::BusDisconnect(imageAsset.GetId());
- if (imageAsset.GetId().IsValid())
- {
- // If the asset is already loaded it'll call OnAssetReady() immediately on BusConnect().
- Data::AssetBus::MultiHandler::BusConnect(imageAsset.GetId());
- imageAsset.QueueLoad();
- }
- else
- {
- // Call update for invalid assets so current assets can be cleared if necessary.
- UpdateWithAsset(imageAsset);
- }
- }
- void HDRiSkyboxComponentController::UpdateWithAsset(Data::Asset<Data::AssetData> updatedAsset)
- {
- if (m_configuration.m_cubemapAsset.GetId() == updatedAsset.GetId())
- {
- m_configuration.m_cubemapAsset = updatedAsset;
- if (IsAssetValid(m_configuration.m_cubemapAsset))
- {
- m_featureProcessorInterface->SetCubemap(RPI::StreamingImage::FindOrCreate(m_configuration.m_cubemapAsset));
- }
- else
- {
- m_featureProcessorInterface->SetCubemap(nullptr);
- }
- }
- }
- bool HDRiSkyboxComponentController::IsAssetValid(Data::Asset<RPI::StreamingImageAsset>& asset)
- {
- if (asset.GetId().IsValid() && asset->IsReady())
- {
- auto& descriptor = asset->GetImageDescriptor();
- bool isCubemap = descriptor.m_isCubemap || descriptor.m_arraySize == 6;
- if (isCubemap)
- {
- return true;
- }
- }
- return false;
- }
- AZ::Matrix4x4 HDRiSkyboxComponentController::GetInverseTransform(const AZ::Transform& world)
- {
- float matrix[16];
- // remove scale
- Transform worldNoScale = world;
- worldNoScale.ExtractUniformScale();
-
- AZ::Matrix3x4 transformMatrix = AZ::Matrix3x4::CreateFromTransform(worldNoScale);
- transformMatrix.StoreToRowMajorFloat12(matrix);
- // remove translation
- matrix[3] = 0;
- matrix[7] = 0;
- matrix[11] = 0;
- matrix[12] = 0;
- matrix[13] = 0;
- matrix[14] = 0;
- matrix[15] = 1;
- return AZ::Matrix4x4::CreateFromRowMajorFloat16(matrix).GetInverseFast();
- }
- } // namespace Render
- } // namespace AZ
|