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.
144 lines
5.6 KiB
C++
144 lines
5.6 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 <Atom/Feature/ImageBasedLights/ImageBasedLightFeatureProcessor.h>
|
|
|
|
#include <Atom/RPI.Public/Scene.h>
|
|
#include <Atom/RPI.Public/Image/StreamingImage.h>
|
|
|
|
#include <Atom/RHI/CpuProfiler.h>
|
|
|
|
#include <AzCore/Debug/EventTrace.h>
|
|
|
|
namespace AZ
|
|
{
|
|
namespace Render
|
|
{
|
|
void ImageBasedLightFeatureProcessor::Reflect(ReflectContext* context)
|
|
{
|
|
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
|
|
{
|
|
serializeContext
|
|
->Class<ImageBasedLightFeatureProcessor, FeatureProcessor>()
|
|
->Version(0);
|
|
}
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::Activate()
|
|
{
|
|
m_sceneSrg = GetParentScene()->GetShaderResourceGroup();
|
|
|
|
// Load default specular and diffuse cubemaps
|
|
// These are assigned when Global IBL is disabled or removed from the scene to prevent a Vulkan TDR.
|
|
// [GFX-TODO][ATOM-4181] This can be removed after Vulkan is changed to automatically handle this issue.
|
|
LoadDefaultCubeMaps();
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::Deactivate()
|
|
{
|
|
m_iblOrientationConstantIndex.Reset();
|
|
m_iblExposureConstantIndex.Reset();
|
|
m_diffuseEnvMapIndex.Reset();
|
|
m_specularEnvMapIndex.Reset();
|
|
m_sceneSrg = {};
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::Simulate(const FeatureProcessor::SimulatePacket& packet)
|
|
{
|
|
AZ_ATOM_PROFILE_FUNCTION("RPI", "ImageBasedLightFeatureProcessor: Simulate");
|
|
AZ_UNUSED(packet);
|
|
|
|
m_sceneSrg->SetImage(m_specularEnvMapIndex, m_specular);
|
|
m_sceneSrg->SetImage(m_diffuseEnvMapIndex, m_diffuse);
|
|
m_sceneSrg->SetConstant(m_iblExposureConstantIndex, m_exposure);
|
|
m_sceneSrg->SetConstant(m_iblOrientationConstantIndex, m_orientation);
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::SetSpecularImage(const Data::Asset<RPI::StreamingImageAsset>& imageAsset)
|
|
{
|
|
m_specular = GetInstanceForImage(imageAsset, m_defaultSpecularImage);
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::SetDiffuseImage(const Data::Asset<RPI::StreamingImageAsset>& imageAsset)
|
|
{
|
|
m_diffuse = GetInstanceForImage(imageAsset, m_defaultDiffuseImage);
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::SetExposure(float exposure)
|
|
{
|
|
m_exposure = exposure;
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::SetOrientation(const Quaternion& orientation)
|
|
{
|
|
m_orientation = orientation;
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::Reset()
|
|
{
|
|
m_specular = m_defaultSpecularImage;
|
|
m_diffuse = m_defaultDiffuseImage;
|
|
m_exposure = 0;
|
|
}
|
|
|
|
void ImageBasedLightFeatureProcessor::LoadDefaultCubeMaps()
|
|
{
|
|
const constexpr char* DefaultSpecularCubeMapPath = "textures/default/default_iblglobalcm_iblspecular.dds.streamingimage";
|
|
const constexpr char* DefaultDiffuseCubeMapPath = "textures/default/default_iblglobalcm_ibldiffuse.dds.streamingimage";
|
|
|
|
Data::AssetId specularAssetId;
|
|
Data::AssetCatalogRequestBus::BroadcastResult(
|
|
specularAssetId,
|
|
&Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
|
|
DefaultSpecularCubeMapPath,
|
|
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
|
|
false);
|
|
|
|
Data::AssetId diffuseAssetId;
|
|
Data::AssetCatalogRequestBus::BroadcastResult(
|
|
diffuseAssetId,
|
|
&Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
|
|
DefaultDiffuseCubeMapPath,
|
|
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
|
|
false);
|
|
|
|
auto specularAsset = Data::AssetManager::Instance().GetAsset<RPI::StreamingImageAsset>(specularAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
|
|
auto diffuseAsset = Data::AssetManager::Instance().GetAsset<RPI::StreamingImageAsset>(diffuseAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
|
|
|
|
specularAsset.BlockUntilLoadComplete();
|
|
diffuseAsset.BlockUntilLoadComplete();
|
|
|
|
m_defaultSpecularImage = RPI::StreamingImage::FindOrCreate(specularAsset);
|
|
AZ_Assert(m_defaultSpecularImage, "Failed to load default specular cubemap");
|
|
|
|
m_defaultDiffuseImage = RPI::StreamingImage::FindOrCreate(diffuseAsset);
|
|
AZ_Assert(m_defaultDiffuseImage, "Failed to load default diffuse cubemap");
|
|
}
|
|
|
|
Data::Instance<RPI::Image> ImageBasedLightFeatureProcessor::GetInstanceForImage(const Data::Asset<RPI::StreamingImageAsset>& imageAsset, const Data::Instance<RPI::Image>& defaultImage)
|
|
{
|
|
Data::Instance<RPI::Image> image;
|
|
if (imageAsset.GetId().IsValid())
|
|
{
|
|
image = RPI::StreamingImage::FindOrCreate(imageAsset);
|
|
if (image && !ValidateIsCubemap(image))
|
|
{
|
|
image = defaultImage;
|
|
}
|
|
}
|
|
return image;
|
|
}
|
|
|
|
bool ImageBasedLightFeatureProcessor::ValidateIsCubemap(Data::Instance<RPI::Image> image)
|
|
{
|
|
const RHI::ImageDescriptor& desc = image->GetRHIImage()->GetDescriptor();
|
|
return (desc.m_isCubemap || desc.m_arraySize == 6);
|
|
}
|
|
} // namespace Render
|
|
} // namespace AZ
|