Added DiffuseProbeGrid texture baking
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
|
||||
"Name": "LUT_R32F",
|
||||
"FileMasks": ["_lutr32f"],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"PixelFormat": "R32F"
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"es3": {
|
||||
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
|
||||
"Name": "LUT_R32F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"PixelFormat": "R32F"
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
|
||||
"Name": "LUT_R32F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"PixelFormat": "R32F"
|
||||
},
|
||||
"osx_gl": {
|
||||
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
|
||||
"Name": "LUT_R32F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"PixelFormat": "R32F"
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
|
||||
"Name": "LUT_R32F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"PixelFormat": "R32F"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}",
|
||||
"Name": "LUT_RGBA16",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16"
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"es3": {
|
||||
"UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}",
|
||||
"Name": "LUT_RGBA16",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16"
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}",
|
||||
"Name": "LUT_RGBA16",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16"
|
||||
},
|
||||
"osx_gl": {
|
||||
"UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}",
|
||||
"Name": "LUT_RGBA16",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16"
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{ABDFCED1-0565-4B7B-9BC1-82C473BCEEA2}",
|
||||
"Name": "LUT_RGBA16",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}",
|
||||
"Name": "LUT_RGBA16F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16f"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16F"
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"es3": {
|
||||
"UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}",
|
||||
"Name": "LUT_RGBA16F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16f"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16F"
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}",
|
||||
"Name": "LUT_RGBA16F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16f"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16F"
|
||||
},
|
||||
"osx_gl": {
|
||||
"UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}",
|
||||
"Name": "LUT_RGBA16F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16f"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16F"
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{6D75F093-C826-437A-AD94-8631A5A4E8A2}",
|
||||
"Name": "LUT_RGBA16F",
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"FileMasks": [
|
||||
"_lutrgba16f"
|
||||
],
|
||||
"PixelFormat": "R16G16B16A16F"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -14,6 +14,9 @@
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <Atom/RPI.Public/FeatureProcessor.h>
|
||||
#include <Atom/RHI.Reflect/Size.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
|
||||
#include <Atom/RPI.Reflect/Image/Image.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -23,6 +26,57 @@ namespace AZ
|
||||
|
||||
using DiffuseProbeGridHandle = AZStd::shared_ptr<DiffuseProbeGrid>;
|
||||
|
||||
enum class DiffuseProbeGridMode : uint8_t
|
||||
{
|
||||
RealTime,
|
||||
Baked,
|
||||
AutoSelect
|
||||
};
|
||||
|
||||
enum class DiffuseProbeGridTextureNotificationType
|
||||
{
|
||||
None,
|
||||
Ready,
|
||||
Error
|
||||
};
|
||||
|
||||
struct DiffuseProbeGridTexture
|
||||
{
|
||||
const AZStd::shared_ptr<AZStd::vector<uint8_t>> m_data;
|
||||
RHI::Format m_format;
|
||||
RHI::Size m_size;
|
||||
};
|
||||
|
||||
static const char* DiffuseProbeGridIrradianceFileName = "Irradiance_lutrgba16.dds";
|
||||
static const char* DiffuseProbeGridDistanceFileName = "Distance_lutrg32f.dds";
|
||||
static const char* DiffuseProbeGridRelocationFileName = "Relocation_lutrgba16f.dds";
|
||||
static const char* DiffuseProbeGridClassificationFileName = "Classification_lutr32f.dds";
|
||||
|
||||
using DiffuseProbeGridBakeTexturesCallback = AZStd::function<void(
|
||||
DiffuseProbeGridTexture irradianceTexture,
|
||||
DiffuseProbeGridTexture distanceTexture,
|
||||
DiffuseProbeGridTexture relocationTexture,
|
||||
DiffuseProbeGridTexture classificationTexture)>;
|
||||
|
||||
struct DiffuseProbeGridBakedTextures
|
||||
{
|
||||
// irradiance and distance images can be used directly
|
||||
Data::Instance<RPI::Image> m_irradianceImage;
|
||||
AZStd::string m_irradianceImageRelativePath;
|
||||
|
||||
Data::Instance<RPI::Image> m_distanceImage;
|
||||
AZStd::string m_distanceImageRelativePath;
|
||||
|
||||
// relocation and classification images need to be recreated as RW textures
|
||||
RHI::ImageDescriptor m_relocationImageDescriptor;
|
||||
AZStd::array_view<uint8_t> m_relocationImageData;
|
||||
AZStd::string m_relocationImageRelativePath;
|
||||
|
||||
RHI::ImageDescriptor m_classificationImageDescriptor;
|
||||
AZStd::array_view<uint8_t> m_classificationImageData;
|
||||
AZStd::string m_classificationImageRelativePath;
|
||||
};
|
||||
|
||||
// DiffuseProbeGridFeatureProcessorInterface provides an interface to the feature processor for code outside of Atom
|
||||
class DiffuseProbeGridFeatureProcessorInterface
|
||||
: public RPI::FeatureProcessor
|
||||
@@ -44,6 +98,28 @@ namespace AZ
|
||||
virtual void Enable(const DiffuseProbeGridHandle& probeGrid, bool enable) = 0;
|
||||
virtual void SetGIShadows(const DiffuseProbeGridHandle& probeGrid, bool giShadows) = 0;
|
||||
virtual void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) = 0;
|
||||
virtual void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) = 0;
|
||||
virtual void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) = 0;
|
||||
|
||||
virtual void BakeTextures(
|
||||
const DiffuseProbeGridHandle& probeGrid,
|
||||
DiffuseProbeGridBakeTexturesCallback callback,
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath) = 0;
|
||||
|
||||
virtual bool CheckTextureAssetNotification(
|
||||
const AZStd::string& relativePath,
|
||||
Data::Asset<RPI::StreamingImageAsset>& outTextureAsset,
|
||||
DiffuseProbeGridTextureNotificationType& outNotificationType) = 0;
|
||||
|
||||
virtual bool AreBakedTexturesReferenced(
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath) = 0;
|
||||
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <Atom/RHI.Reflect/ShaderResourceGroupLayoutDescriptor.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGrid.h>
|
||||
#include <Atom/RPI.Public/Image/StreamingImage.h>
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RHI/Factory.h>
|
||||
@@ -23,6 +24,11 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
DiffuseProbeGrid::DiffuseProbeGrid()
|
||||
: m_textureReadback(this)
|
||||
{
|
||||
}
|
||||
|
||||
DiffuseProbeGrid::~DiffuseProbeGrid()
|
||||
{
|
||||
m_scene->GetCullingScene()->UnregisterCullable(m_cullable);
|
||||
@@ -166,6 +172,84 @@ namespace AZ
|
||||
m_updateRenderObjectSrg = true;
|
||||
}
|
||||
|
||||
void DiffuseProbeGrid::SetMode(DiffuseProbeGridMode mode)
|
||||
{
|
||||
// handle auto-select
|
||||
if (mode == DiffuseProbeGridMode::AutoSelect)
|
||||
{
|
||||
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
|
||||
m_mode = (device->GetFeatures().m_rayTracing) ? DiffuseProbeGridMode::RealTime : DiffuseProbeGridMode::Baked;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
m_updateTextures = true;
|
||||
}
|
||||
|
||||
void DiffuseProbeGrid::SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures)
|
||||
{
|
||||
AZ_Assert(bakedTextures.m_irradianceImage.get(), "Invalid Irradiance image passed to SetBakedTextures");
|
||||
AZ_Assert(bakedTextures.m_distanceImage.get(), "Invalid Distance image passed to SetBakedTextures");
|
||||
AZ_Assert(bakedTextures.m_relocationImageData.size() > 0, "Invalid Relocation image data passed to SetBakedTextures");
|
||||
AZ_Assert(bakedTextures.m_classificationImageData.size() > 0, "Invalid Classification image data passed to SetBakedTextures");
|
||||
|
||||
m_bakedIrradianceImage = bakedTextures.m_irradianceImage;
|
||||
m_bakedDistanceImage = bakedTextures.m_distanceImage;
|
||||
|
||||
m_bakedIrradianceRelativePath = bakedTextures.m_irradianceImageRelativePath;
|
||||
m_bakedDistanceRelativePath = bakedTextures.m_distanceImageRelativePath;
|
||||
m_bakedRelocationRelativePath = bakedTextures.m_relocationImageRelativePath;
|
||||
m_bakedClassificationRelativePath = bakedTextures.m_classificationImageRelativePath;
|
||||
|
||||
m_bakedRelocationImageData.resize(bakedTextures.m_relocationImageData.size());
|
||||
memcpy(m_bakedRelocationImageData.data(), bakedTextures.m_relocationImageData.data(), bakedTextures.m_relocationImageData.size());
|
||||
|
||||
m_bakedClassificationImageData.resize(bakedTextures.m_classificationImageData.size());
|
||||
memcpy(m_bakedClassificationImageData.data(), bakedTextures.m_classificationImageData.data(), bakedTextures.m_classificationImageData.size());
|
||||
|
||||
// create the relocation and distance RW textures now, these are needed for shader compatibility
|
||||
// (image data is copied in UpdateTextures)
|
||||
{
|
||||
m_bakedRelocationImage = RHI::Factory::Get().CreateImage();
|
||||
RHI::ImageInitRequest initRequest;
|
||||
initRequest.m_image = m_bakedRelocationImage.get();
|
||||
initRequest.m_descriptor = RHI::ImageDescriptor::Create2D(
|
||||
RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead,
|
||||
bakedTextures.m_relocationImageDescriptor.m_size.m_width,
|
||||
bakedTextures.m_relocationImageDescriptor.m_size.m_height,
|
||||
bakedTextures.m_relocationImageDescriptor.m_format);
|
||||
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(initRequest);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize Relocation image");
|
||||
}
|
||||
|
||||
{
|
||||
m_bakedClassificationImage = RHI::Factory::Get().CreateImage();
|
||||
RHI::ImageInitRequest initRequest;
|
||||
initRequest.m_image = m_bakedClassificationImage.get();
|
||||
initRequest.m_descriptor = RHI::ImageDescriptor::Create2D(
|
||||
RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead,
|
||||
bakedTextures.m_classificationImageDescriptor.m_size.m_width,
|
||||
bakedTextures.m_classificationImageDescriptor.m_size.m_height,
|
||||
bakedTextures.m_classificationImageDescriptor.m_format);
|
||||
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(initRequest);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize Classification image");
|
||||
}
|
||||
|
||||
m_updateTextures = true;
|
||||
}
|
||||
|
||||
bool DiffuseProbeGrid::HasValidBakedTextures() const
|
||||
{
|
||||
return m_bakedIrradianceImage.get() &&
|
||||
m_bakedDistanceImage.get() &&
|
||||
m_bakedRelocationImage.get() &&
|
||||
m_bakedClassificationImage.get();
|
||||
}
|
||||
|
||||
uint32_t DiffuseProbeGrid::GetTotalProbeCount() const
|
||||
{
|
||||
return m_probeCountX * m_probeCountY * m_probeCountZ;
|
||||
@@ -188,83 +272,117 @@ namespace AZ
|
||||
|
||||
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
|
||||
|
||||
// advance to the next image in the frame image array
|
||||
m_currentImageIndex = (m_currentImageIndex + 1) % ImageFrameCount;
|
||||
|
||||
// probe raytrace
|
||||
{
|
||||
uint32_t width = m_numRaysPerProbe;
|
||||
uint32_t height = GetTotalProbeCount();
|
||||
|
||||
m_rayTraceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_rayTraceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::RayTraceImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRayTraceImage image");
|
||||
}
|
||||
|
||||
uint32_t probeCountX;
|
||||
uint32_t probeCountY;
|
||||
GetTexture2DProbeCount(probeCountX, probeCountY);
|
||||
|
||||
// probe irradiance
|
||||
if (m_mode == DiffuseProbeGridMode::RealTime)
|
||||
{
|
||||
uint32_t width = probeCountX * (DefaultNumIrradianceTexels + 2);
|
||||
uint32_t height = probeCountY * (DefaultNumIrradianceTexels + 2);
|
||||
// advance to the next image in the frame image array
|
||||
m_currentImageIndex = (m_currentImageIndex + 1) % ImageFrameCount;
|
||||
|
||||
m_irradianceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
// probe raytrace
|
||||
{
|
||||
uint32_t width = m_numRaysPerProbe;
|
||||
uint32_t height = GetTotalProbeCount();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_irradianceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::IrradianceImageFormat);
|
||||
RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
request.m_optimizedClearValue = &clearValue;
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeIrradianceImage image");
|
||||
m_rayTraceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_rayTraceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::RayTraceImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRayTraceImage image");
|
||||
}
|
||||
|
||||
// probe irradiance
|
||||
{
|
||||
uint32_t width = probeCountX * (DefaultNumIrradianceTexels + 2);
|
||||
uint32_t height = probeCountY * (DefaultNumIrradianceTexels + 2);
|
||||
|
||||
m_irradianceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_irradianceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::IrradianceImageFormat);
|
||||
RHI::ClearValue clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
request.m_optimizedClearValue = &clearValue;
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeIrradianceImage image");
|
||||
}
|
||||
|
||||
// probe distance
|
||||
{
|
||||
uint32_t width = probeCountX * (DefaultNumDistanceTexels + 2);
|
||||
uint32_t height = probeCountY * (DefaultNumDistanceTexels + 2);
|
||||
|
||||
m_distanceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_distanceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::DistanceImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDistanceImage image");
|
||||
}
|
||||
|
||||
// probe relocation
|
||||
{
|
||||
uint32_t width = probeCountX;
|
||||
uint32_t height = probeCountY;
|
||||
|
||||
m_relocationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_relocationImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::RelocationImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRelocationImage image");
|
||||
}
|
||||
|
||||
// probe classification
|
||||
{
|
||||
uint32_t width = probeCountX;
|
||||
uint32_t height = probeCountY;
|
||||
|
||||
m_classificationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_classificationImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead, width, height, DiffuseProbeGridRenderData::ClassificationImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeClassificationImage image");
|
||||
}
|
||||
}
|
||||
|
||||
// probe distance
|
||||
else if (m_mode == DiffuseProbeGridMode::Baked && HasValidBakedTextures())
|
||||
{
|
||||
uint32_t width = probeCountX * (DefaultNumDistanceTexels + 2);
|
||||
uint32_t height = probeCountY * (DefaultNumDistanceTexels + 2);
|
||||
// copy the baked relocation and classification texture data to the RW textures
|
||||
// (these need to be RW for shader compatibility)
|
||||
RHI::ImageSubresourceRange range{ 0, 0, 0 ,0 };
|
||||
RHI::ImageSubresourceLayoutPlaced layout;
|
||||
|
||||
m_distanceImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
// relocation
|
||||
{
|
||||
m_bakedRelocationImage->GetSubresourceLayouts(range, &layout, nullptr);
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_distanceImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::DistanceImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDistanceImage image");
|
||||
}
|
||||
RHI::ImageUpdateRequest updateRequest;
|
||||
updateRequest.m_image = m_bakedRelocationImage.get();
|
||||
updateRequest.m_sourceSubresourceLayout = layout;
|
||||
updateRequest.m_sourceData = m_bakedRelocationImageData.data();
|
||||
updateRequest.m_imageSubresourcePixelOffset = RHI::Origin(0, 0, 0);
|
||||
m_renderData->m_imagePool->UpdateImageContents(updateRequest);
|
||||
}
|
||||
|
||||
// probe relocation
|
||||
{
|
||||
uint32_t width = probeCountX;
|
||||
uint32_t height = probeCountY;
|
||||
// classification
|
||||
{
|
||||
m_bakedClassificationImage->GetSubresourceLayouts(range, &layout, nullptr);
|
||||
|
||||
m_relocationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_relocationImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::RelocationImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeRelocationImage image");
|
||||
}
|
||||
|
||||
// probe classification
|
||||
{
|
||||
uint32_t width = probeCountX;
|
||||
uint32_t height = probeCountY;
|
||||
|
||||
m_classificationImage[m_currentImageIndex] = RHI::Factory::Get().CreateImage();
|
||||
|
||||
RHI::ImageInitRequest request;
|
||||
request.m_image = m_classificationImage[m_currentImageIndex].get();
|
||||
request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, width, height, DiffuseProbeGridRenderData::ClassificationImageFormat);
|
||||
[[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request);
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeClassificationImage image");
|
||||
RHI::ImageUpdateRequest updateRequest;
|
||||
updateRequest.m_image = m_bakedClassificationImage.get();
|
||||
updateRequest.m_sourceSubresourceLayout = layout;
|
||||
updateRequest.m_sourceData = m_bakedClassificationImageData.data();
|
||||
updateRequest.m_imageSubresourcePixelOffset = RHI::Origin(0, 0, 0);
|
||||
m_renderData->m_imagePool->UpdateImageContents(updateRequest);
|
||||
}
|
||||
}
|
||||
|
||||
m_updateTextures = false;
|
||||
@@ -639,16 +757,16 @@ namespace AZ
|
||||
m_renderObjectSrg->SetConstant(constantIndex, m_ambientMultiplier);
|
||||
|
||||
imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeIrradiance"));
|
||||
m_renderObjectSrg->SetImageView(imageIndex, m_irradianceImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get());
|
||||
m_renderObjectSrg->SetImageView(imageIndex, GetIrradianceImage()->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get());
|
||||
|
||||
imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeDistance"));
|
||||
m_renderObjectSrg->SetImageView(imageIndex, m_distanceImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get());
|
||||
m_renderObjectSrg->SetImageView(imageIndex, GetDistanceImage()->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get());
|
||||
|
||||
imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeOffsets"));
|
||||
m_renderObjectSrg->SetImageView(imageIndex, m_relocationImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeRelocationImageViewDescriptor).get());
|
||||
m_renderObjectSrg->SetImageView(imageIndex, GetRelocationImage()->GetImageView(m_renderData->m_probeRelocationImageViewDescriptor).get());
|
||||
|
||||
imageIndex = srgLayout->FindShaderInputImageIndex(Name("m_probeStates"));
|
||||
m_renderObjectSrg->SetImageView(imageIndex, m_classificationImage[m_currentImageIndex]->GetImageView(m_renderData->m_probeClassificationImageViewDescriptor).get());
|
||||
m_renderObjectSrg->SetImageView(imageIndex, GetClassificationImage()->GetImageView(m_renderData->m_probeClassificationImageViewDescriptor).get());
|
||||
|
||||
SetGridConstants(m_renderObjectSrg);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <AzCore/Math/Random.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace AZ
|
||||
static const RHI::Format IrradianceImageFormat = RHI::Format::R16G16B16A16_UNORM;
|
||||
static const RHI::Format DistanceImageFormat = RHI::Format::R32G32_FLOAT;
|
||||
static const RHI::Format RelocationImageFormat = RHI::Format::R16G16B16A16_FLOAT;
|
||||
static const RHI::Format ClassificationImageFormat = RHI::Format::R8_UINT;
|
||||
static const RHI::Format ClassificationImageFormat = RHI::Format::R32_FLOAT;
|
||||
|
||||
// image pool
|
||||
RHI::Ptr<RHI::ImagePool> m_imagePool;
|
||||
@@ -61,7 +62,7 @@ namespace AZ
|
||||
class DiffuseProbeGrid final
|
||||
{
|
||||
public:
|
||||
DiffuseProbeGrid() = default;
|
||||
DiffuseProbeGrid();
|
||||
~DiffuseProbeGrid();
|
||||
|
||||
void Init(RPI::Scene* scene, DiffuseProbeGridRenderData* diffuseProbeGridRenderData);
|
||||
@@ -96,6 +97,9 @@ namespace AZ
|
||||
bool GetUseDiffuseIbl() const { return m_useDiffuseIbl; }
|
||||
void SetUseDiffuseIbl(bool useDiffuseIbl) { m_useDiffuseIbl = useDiffuseIbl; }
|
||||
|
||||
DiffuseProbeGridMode GetMode() const { return m_mode; }
|
||||
void SetMode(DiffuseProbeGridMode mode);
|
||||
|
||||
uint32_t GetNumRaysPerProbe() const { return m_numRaysPerProbe; }
|
||||
|
||||
uint32_t GetRemainingRelocationIterations() const { return aznumeric_cast<uint32_t>(m_remainingRelocationIterations); }
|
||||
@@ -133,11 +137,16 @@ namespace AZ
|
||||
void UpdateRenderObjectSrg();
|
||||
|
||||
// textures
|
||||
const RHI::Ptr<RHI::Image>& GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image>& GetIrradianceImage() { return m_irradianceImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image>& GetDistanceImage() { return m_distanceImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image>& GetRelocationImage() { return m_relocationImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image>& GetClassificationImage() { return m_classificationImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image> GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; }
|
||||
const RHI::Ptr<RHI::Image> GetIrradianceImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_irradianceImage[m_currentImageIndex] : m_bakedIrradianceImage->GetRHIImage(); }
|
||||
const RHI::Ptr<RHI::Image> GetDistanceImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_distanceImage[m_currentImageIndex] : m_bakedDistanceImage->GetRHIImage(); }
|
||||
const RHI::Ptr<RHI::Image> GetRelocationImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_relocationImage[m_currentImageIndex] : m_bakedRelocationImage; }
|
||||
const RHI::Ptr<RHI::Image> GetClassificationImage() { return m_mode == DiffuseProbeGridMode::RealTime ? m_classificationImage[m_currentImageIndex] : m_bakedClassificationImage; }
|
||||
|
||||
const AZStd::string& GetBakedIrradianceRelativePath() const { return m_bakedIrradianceRelativePath; }
|
||||
const AZStd::string& GetBakedDistanceRelativePath() const { return m_bakedDistanceRelativePath; }
|
||||
const AZStd::string& GetBakedRelocationRelativePath() const { return m_bakedRelocationRelativePath; }
|
||||
const AZStd::string& GetBakedClassificationRelativePath() const { return m_bakedClassificationRelativePath; }
|
||||
|
||||
// attachment Ids
|
||||
const RHI::AttachmentId GetRayTraceImageAttachmentId() const { return m_rayTraceImageAttachmentId; }
|
||||
@@ -152,6 +161,12 @@ namespace AZ
|
||||
bool GetIrradianceClearRequired() const { return m_irradianceClearRequired; }
|
||||
void ResetIrradianceClearRequired() { m_irradianceClearRequired = false; }
|
||||
|
||||
// texture readback
|
||||
DiffuseProbeGridTextureReadback& GetTextureReadback() { return m_textureReadback; }
|
||||
|
||||
void SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures);
|
||||
bool HasValidBakedTextures() const;
|
||||
|
||||
static constexpr uint32_t DefaultNumIrradianceTexels = 6;
|
||||
static constexpr uint32_t DefaultNumDistanceTexels = 14;
|
||||
static constexpr int32_t DefaultNumRelocationIterations = 100;
|
||||
@@ -221,7 +236,10 @@ namespace AZ
|
||||
// culling
|
||||
RPI::Cullable m_cullable;
|
||||
|
||||
// textures
|
||||
// grid mode (RealTime or Baked)
|
||||
DiffuseProbeGridMode m_mode = DiffuseProbeGridMode::RealTime;
|
||||
|
||||
// real-time textures
|
||||
static const uint32_t MaxTextureDimension = 8192;
|
||||
static const uint32_t ImageFrameCount = 3;
|
||||
RHI::Ptr<RHI::Image> m_rayTraceImage[ImageFrameCount];
|
||||
@@ -233,6 +251,25 @@ namespace AZ
|
||||
bool m_updateTextures = false;
|
||||
bool m_irradianceClearRequired = true;
|
||||
|
||||
// baked textures
|
||||
Data::Instance<RPI::Image> m_bakedIrradianceImage;
|
||||
Data::Instance<RPI::Image> m_bakedDistanceImage;
|
||||
RHI::Ptr<RHI::Image> m_bakedRelocationImage;
|
||||
RHI::Ptr<RHI::Image> m_bakedClassificationImage;
|
||||
|
||||
// baked texture relative paths
|
||||
AZStd::string m_bakedIrradianceRelativePath;
|
||||
AZStd::string m_bakedDistanceRelativePath;
|
||||
AZStd::string m_bakedRelocationRelativePath;
|
||||
AZStd::string m_bakedClassificationRelativePath;
|
||||
|
||||
// baked texture data (only needed for the relocation and classification textures)
|
||||
AZStd::vector<uint8_t> m_bakedRelocationImageData;
|
||||
AZStd::vector<uint8_t> m_bakedClassificationImageData;
|
||||
|
||||
// texture readback
|
||||
DiffuseProbeGridTextureReadback m_textureReadback;
|
||||
|
||||
// Srgs
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_rayTraceSrg;
|
||||
Data::Instance<RPI::ShaderResourceGroup> m_blendIrradianceSrg;
|
||||
|
||||
+4
-4
@@ -87,7 +87,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -111,7 +111,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// probe raytrace image
|
||||
{
|
||||
@@ -150,7 +150,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -167,7 +167,7 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
// submit the DispatchItem for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBlendDistanceSrg()->GetRHIShaderResourceGroup();
|
||||
commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
|
||||
|
||||
+4
-4
@@ -87,7 +87,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -111,7 +111,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// probe raytrace image
|
||||
{
|
||||
@@ -150,7 +150,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -167,7 +167,7 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
// submit the DispatchItem for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBlendIrradianceSrg()->GetRHIShaderResourceGroup();
|
||||
commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
|
||||
|
||||
+4
-4
@@ -100,7 +100,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -124,7 +124,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// probe irradiance image
|
||||
{
|
||||
@@ -153,7 +153,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see line ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -173,7 +173,7 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
// submit the DispatchItems for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
uint32_t probeCountX;
|
||||
uint32_t probeCountY;
|
||||
|
||||
+4
-4
@@ -91,7 +91,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -115,7 +115,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// probe raytrace image
|
||||
{
|
||||
@@ -143,7 +143,7 @@ namespace AZ
|
||||
{
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -159,7 +159,7 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
// submit the DispatchItems for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetClassificationSrg()->GetRHIShaderResourceGroup();
|
||||
commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
|
||||
|
||||
+201
-1
@@ -45,6 +45,7 @@ namespace AZ
|
||||
RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
|
||||
|
||||
m_diffuseProbeGrids.reserve(InitialProbeGridAllocationSize);
|
||||
m_realTimeDiffuseProbeGrids.reserve(InitialProbeGridAllocationSize);
|
||||
|
||||
RHI::BufferPoolDescriptor desc;
|
||||
desc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
|
||||
@@ -61,7 +62,7 @@ namespace AZ
|
||||
// image pool
|
||||
{
|
||||
RHI::ImagePoolDescriptor imagePoolDesc;
|
||||
imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite;
|
||||
imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead;
|
||||
|
||||
m_probeGridRenderData.m_imagePool = RHI::Factory::Get().CreateImagePool();
|
||||
[[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*rhiSystem->GetDevice(), imagePoolDesc);
|
||||
@@ -123,6 +124,32 @@ namespace AZ
|
||||
m_needUpdatePipelineStates = false;
|
||||
}
|
||||
|
||||
// check pending textures and connect bus for notifications
|
||||
for (auto& notificationEntry : m_notifyTextureAssets)
|
||||
{
|
||||
if (notificationEntry.m_assetId.IsValid())
|
||||
{
|
||||
// asset already has an assetId
|
||||
continue;
|
||||
}
|
||||
|
||||
// query for the assetId
|
||||
AZ::Data::AssetId assetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
assetId,
|
||||
&AZ::Data::AssetCatalogRequests::GetAssetIdByPath,
|
||||
notificationEntry.m_relativePath.c_str(),
|
||||
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
|
||||
false);
|
||||
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
notificationEntry.m_assetId = assetId;
|
||||
notificationEntry.m_asset.Create(assetId, true);
|
||||
Data::AssetBus::MultiHandler::BusConnect(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
// if the volumes changed we need to re-sort the probe list
|
||||
if (m_probeGridSortRequired)
|
||||
{
|
||||
@@ -139,6 +166,7 @@ namespace AZ
|
||||
};
|
||||
|
||||
AZStd::sort(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), sortFn);
|
||||
AZStd::sort(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), sortFn);
|
||||
m_probeGridSortRequired = false;
|
||||
}
|
||||
|
||||
@@ -160,6 +188,9 @@ namespace AZ
|
||||
diffuseProbeGrid->SetExtents(extents);
|
||||
diffuseProbeGrid->SetProbeSpacing(probeSpacing);
|
||||
m_diffuseProbeGrids.push_back(diffuseProbeGrid);
|
||||
|
||||
UpdateRealTimeList(diffuseProbeGrid);
|
||||
|
||||
m_probeGridSortRequired = true;
|
||||
|
||||
return diffuseProbeGrid;
|
||||
@@ -169,6 +200,7 @@ namespace AZ
|
||||
{
|
||||
AZ_Assert(probeGrid.get(), "RemoveProbeGrid called with an invalid handle");
|
||||
|
||||
// remove from main list
|
||||
auto itEntry = AZStd::find_if(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
|
||||
{
|
||||
return (entry == probeGrid);
|
||||
@@ -176,6 +208,18 @@ namespace AZ
|
||||
|
||||
AZ_Assert(itEntry != m_diffuseProbeGrids.end(), "RemoveProbeGrid called with a probe grid that is not in the probe list");
|
||||
m_diffuseProbeGrids.erase(itEntry);
|
||||
|
||||
// remove from side list of real-time grids
|
||||
itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
|
||||
{
|
||||
return (entry == probeGrid);
|
||||
});
|
||||
|
||||
if (itEntry != m_realTimeDiffuseProbeGrids.end())
|
||||
{
|
||||
m_realTimeDiffuseProbeGrids.erase(itEntry);
|
||||
}
|
||||
|
||||
probeGrid = nullptr;
|
||||
}
|
||||
|
||||
@@ -247,6 +291,133 @@ namespace AZ
|
||||
probeGrid->SetUseDiffuseIbl(useDiffuseIbl);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::BakeTextures(
|
||||
const DiffuseProbeGridHandle& probeGrid,
|
||||
DiffuseProbeGridBakeTexturesCallback callback,
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath)
|
||||
{
|
||||
AZ_Assert(probeGrid.get(), "BakeTextures called with an invalid handle");
|
||||
|
||||
AddNotificationEntry(irradianceTextureRelativePath);
|
||||
AddNotificationEntry(distanceTextureRelativePath);
|
||||
AddNotificationEntry(relocationTextureRelativePath);
|
||||
AddNotificationEntry(classificationTextureRelativePath);
|
||||
|
||||
probeGrid->GetTextureReadback().BeginTextureReadback(callback);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::UpdateRealTimeList(const DiffuseProbeGridHandle& diffuseProbeGrid)
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime)
|
||||
{
|
||||
// add to side list of real-time grids
|
||||
auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
|
||||
{
|
||||
return (entry == diffuseProbeGrid);
|
||||
});
|
||||
|
||||
if (itEntry == m_realTimeDiffuseProbeGrids.end())
|
||||
{
|
||||
m_realTimeDiffuseProbeGrids.push_back(diffuseProbeGrid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove from side list of real-time grids
|
||||
auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
|
||||
{
|
||||
return (entry == diffuseProbeGrid);
|
||||
});
|
||||
|
||||
if (itEntry != m_realTimeDiffuseProbeGrids.end())
|
||||
{
|
||||
m_realTimeDiffuseProbeGrids.erase(itEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::AddNotificationEntry(const AZStd::string& relativePath)
|
||||
{
|
||||
AZStd::string assetPath = relativePath + ".streamingimage";
|
||||
|
||||
// check to see if this is an existing asset
|
||||
AZ::Data::AssetId assetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
assetId,
|
||||
&AZ::Data::AssetCatalogRequests::GetAssetIdByPath,
|
||||
assetPath.c_str(),
|
||||
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
|
||||
false);
|
||||
|
||||
// we only track notifications for new texture assets, existing assets are automatically reloaded by the RPI
|
||||
if (!assetId.IsValid())
|
||||
{
|
||||
m_notifyTextureAssets.push_back({ assetPath, assetId });
|
||||
}
|
||||
}
|
||||
|
||||
bool DiffuseProbeGridFeatureProcessor::CheckTextureAssetNotification(
|
||||
const AZStd::string& relativePath,
|
||||
Data::Asset<RPI::StreamingImageAsset>& outTextureAsset,
|
||||
DiffuseProbeGridTextureNotificationType& outNotificationType)
|
||||
{
|
||||
for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification)
|
||||
{
|
||||
if (itNotification->m_relativePath == relativePath)
|
||||
{
|
||||
outNotificationType = itNotification->m_notificationType;
|
||||
if (outNotificationType != DiffuseProbeGridTextureNotificationType::None)
|
||||
{
|
||||
outTextureAsset = itNotification->m_asset;
|
||||
m_notifyTextureAssets.erase(itNotification);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiffuseProbeGridFeatureProcessor::AreBakedTexturesReferenced(
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath)
|
||||
{
|
||||
for (auto& diffuseProbeGrid : m_diffuseProbeGrids)
|
||||
{
|
||||
if ((diffuseProbeGrid->GetBakedIrradianceRelativePath() == irradianceTextureRelativePath) ||
|
||||
(diffuseProbeGrid->GetBakedDistanceRelativePath() == distanceTextureRelativePath) ||
|
||||
(diffuseProbeGrid->GetBakedRelocationRelativePath() == relocationTextureRelativePath) ||
|
||||
(diffuseProbeGrid->GetBakedClassificationRelativePath() == classificationTextureRelativePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode)
|
||||
{
|
||||
AZ_Assert(probeGrid.get(), "SetMode called with an invalid handle");
|
||||
probeGrid->SetMode(mode);
|
||||
|
||||
UpdateRealTimeList(probeGrid);
|
||||
|
||||
m_probeGridSortRequired = true;
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures)
|
||||
{
|
||||
AZ_Assert(probeGrid.get(), "SetBakedTextures called with an invalid handle");
|
||||
probeGrid->SetBakedTextures(bakedTextures);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::CreateBoxMesh()
|
||||
{
|
||||
// vertex positions
|
||||
@@ -418,5 +589,34 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::HandleAssetNotification(Data::Asset<Data::AssetData> asset, DiffuseProbeGridTextureNotificationType notificationType)
|
||||
{
|
||||
for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification)
|
||||
{
|
||||
if (itNotification->m_assetId == asset.GetId())
|
||||
{
|
||||
// store the texture asset
|
||||
itNotification->m_asset = Data::static_pointer_cast<RPI::StreamingImageAsset>(asset);
|
||||
itNotification->m_notificationType = notificationType;
|
||||
|
||||
// stop notifications on this asset
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(itNotification->m_assetId);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::OnAssetReady(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridFeatureProcessor::OnAssetError(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str());
|
||||
|
||||
HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error);
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+53
-1
@@ -22,6 +22,7 @@ namespace AZ
|
||||
//! This class manages DiffuseProbeGrids which generate diffuse global illumination
|
||||
class DiffuseProbeGridFeatureProcessor final
|
||||
: public DiffuseProbeGridFeatureProcessorInterface
|
||||
, private Data::AssetBus::MultiHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::DiffuseProbeGridFeatureProcessor, "{BCD232F9-1EBF-4D0D-A5F4-84AEC933A93C}", DiffuseProbeGridFeatureProcessorInterface);
|
||||
@@ -46,6 +47,27 @@ namespace AZ
|
||||
void Enable(const DiffuseProbeGridHandle& probeGrid, bool enable) override;
|
||||
void SetGIShadows(const DiffuseProbeGridHandle& probeGrid, bool giShadows) override;
|
||||
void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) override;
|
||||
void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) override;
|
||||
void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) override;
|
||||
|
||||
void BakeTextures(
|
||||
const DiffuseProbeGridHandle& probeGrid,
|
||||
DiffuseProbeGridBakeTexturesCallback callback,
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath) override;
|
||||
|
||||
bool CheckTextureAssetNotification(
|
||||
const AZStd::string& relativePath,
|
||||
Data::Asset<RPI::StreamingImageAsset>& outTextureAsset,
|
||||
DiffuseProbeGridTextureNotificationType& outNotificationType) override;
|
||||
|
||||
bool AreBakedTexturesReferenced(
|
||||
const AZStd::string& irradianceTextureRelativePath,
|
||||
const AZStd::string& distanceTextureRelativePath,
|
||||
const AZStd::string& relocationTextureRelativePath,
|
||||
const AZStd::string& classificationTextureRelativePath) override;
|
||||
|
||||
// FeatureProcessor overrides
|
||||
void Activate() override;
|
||||
@@ -56,12 +78,28 @@ namespace AZ
|
||||
using DiffuseProbeGridVector = AZStd::vector<AZStd::shared_ptr<DiffuseProbeGrid>>;
|
||||
DiffuseProbeGridVector& GetProbeGrids() { return m_diffuseProbeGrids; }
|
||||
|
||||
// retrieve the side list of probe grids that are using real-time (raytraced) mode
|
||||
DiffuseProbeGridVector& GetRealTimeProbeGrids() { return m_realTimeDiffuseProbeGrids; }
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(DiffuseProbeGridFeatureProcessor);
|
||||
|
||||
// create the box vertex and index streams, which are used to render the probe volumes
|
||||
void CreateBoxMesh();
|
||||
|
||||
// AssetBus::MultiHandler overrides...
|
||||
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
|
||||
void OnAssetError(Data::Asset<Data::AssetData> asset) override;
|
||||
|
||||
// updates the real-time list for a specific probe grid
|
||||
void UpdateRealTimeList(const DiffuseProbeGridHandle& diffuseProbeGrid);
|
||||
|
||||
// adds a notification entry for a new asset
|
||||
void AddNotificationEntry(const AZStd::string& relativePath);
|
||||
|
||||
// notifies and removes the notification entry
|
||||
void HandleAssetNotification(Data::Asset<Data::AssetData> asset, DiffuseProbeGridTextureNotificationType notificationType);
|
||||
|
||||
// RPI::SceneNotificationBus::Handler overrides
|
||||
void OnRenderPipelinePassesChanged(RPI::RenderPipeline* renderPipeline) override;
|
||||
void OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) override;
|
||||
@@ -70,10 +108,13 @@ namespace AZ
|
||||
void UpdatePipelineStates();
|
||||
void UpdatePasses();
|
||||
|
||||
// list of diffuse probe grids
|
||||
// list of all diffuse probe grids
|
||||
const size_t InitialProbeGridAllocationSize = 64;
|
||||
DiffuseProbeGridVector m_diffuseProbeGrids;
|
||||
|
||||
// side list of diffuse probe grids that are in real-time mode (subset of m_diffuseProbeGrids)
|
||||
DiffuseProbeGridVector m_realTimeDiffuseProbeGrids;
|
||||
|
||||
// position structure for the box vertices
|
||||
struct Position
|
||||
{
|
||||
@@ -102,6 +143,17 @@ namespace AZ
|
||||
|
||||
// indicates the the diffuse probe grid render pipeline state needs to be updated
|
||||
bool m_needUpdatePipelineStates = false;
|
||||
|
||||
// list of texture assets that we need to check during Simulate() to see if they are ready
|
||||
struct NotifyTextureAssetEntry
|
||||
{
|
||||
AZStd::string m_relativePath;
|
||||
AZ::Data::AssetId m_assetId;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_asset;
|
||||
DiffuseProbeGridTextureNotificationType m_notificationType = DiffuseProbeGridTextureNotificationType::None;
|
||||
};
|
||||
typedef AZStd::vector<NotifyTextureAssetEntry> NotifyTextureAssetVector;
|
||||
NotifyTextureAssetVector m_notifyTextureAssets;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+5
-5
@@ -132,7 +132,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -210,10 +210,10 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
|
||||
|
||||
frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetProbeGrids().size()));
|
||||
frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().size()));
|
||||
frameGraph.ExecuteAfter(m_rayTracingScopeProducerShaderTable->GetScopeId());
|
||||
|
||||
for (const auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (const auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// TLAS
|
||||
{
|
||||
@@ -318,7 +318,7 @@ namespace AZ
|
||||
rayTracingFeatureProcessor->GetMeshInfoBuffer() &&
|
||||
rayTracingFeatureProcessor->GetSubMeshCount())
|
||||
{
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader
|
||||
// inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -341,7 +341,7 @@ namespace AZ
|
||||
m_rayTracingShaderTable)
|
||||
{
|
||||
// submit the DispatchRaysItem for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
const RHI::ShaderResourceGroup* shaderResourceGroups[] = {
|
||||
diffuseProbeGrid->GetRayTraceSrg()->GetRHIShaderResourceGroup(),
|
||||
|
||||
+5
-5
@@ -91,7 +91,7 @@ namespace AZ
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty())
|
||||
if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids().empty())
|
||||
{
|
||||
// no diffuse probe grids
|
||||
return;
|
||||
@@ -108,7 +108,7 @@ namespace AZ
|
||||
|
||||
// create the Relocation Srgs for each DiffuseProbeGrid, and check to see if any grids need relocation
|
||||
bool needRelocation = false;
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision();
|
||||
if (rayTracingDataRevision != m_rayTracingDataRevision)
|
||||
@@ -139,7 +139,7 @@ namespace AZ
|
||||
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// probe raytrace image
|
||||
{
|
||||
@@ -167,7 +167,7 @@ namespace AZ
|
||||
{
|
||||
RPI::Scene* scene = m_pipeline->GetScene();
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see ValidateSetImageView() in ShaderResourceGroupData.cpp)
|
||||
@@ -187,7 +187,7 @@ namespace AZ
|
||||
DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
|
||||
|
||||
// submit the DispatchItems for each DiffuseProbeGrid
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetRelocationSrg()->GetRHIShaderResourceGroup();
|
||||
commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
|
||||
|
||||
@@ -79,6 +79,12 @@ namespace AZ
|
||||
params.m_scissorState = scissor;
|
||||
|
||||
Base::FrameBeginInternal(params);
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetRealTimeProbeGrids())
|
||||
{
|
||||
// process attachment readback
|
||||
diffuseProbeGrid->GetTextureReadback().FrameBegin(params);
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseProbeGridRenderPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
|
||||
@@ -88,8 +94,21 @@ namespace AZ
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked &&
|
||||
!diffuseProbeGrid->HasValidBakedTextures())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// probe irradiance image
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked)
|
||||
{
|
||||
// import the irradiance image now, since it is baked and therefore was not imported during the raytracing pass
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetIrradianceImageAttachmentId(), diffuseProbeGrid->GetIrradianceImage());
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeIrradianceImage");
|
||||
}
|
||||
|
||||
RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId();
|
||||
desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor;
|
||||
@@ -100,6 +119,13 @@ namespace AZ
|
||||
|
||||
// probe distance image
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked)
|
||||
{
|
||||
// import the distance image now, since it is baked and therefore was not imported during the raytracing pass
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetDistanceImageAttachmentId(), diffuseProbeGrid->GetDistanceImage());
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeDistanceImage");
|
||||
}
|
||||
|
||||
RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId();
|
||||
desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor;
|
||||
@@ -110,6 +136,13 @@ namespace AZ
|
||||
|
||||
// probe relocation image
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked)
|
||||
{
|
||||
// import the relocation image now, since it is baked and therefore was not imported during the raytracing pass
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetRelocationImageAttachmentId(), diffuseProbeGrid->GetRelocationImage());
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeRelocationImage");
|
||||
}
|
||||
|
||||
RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = diffuseProbeGrid->GetRelocationImageAttachmentId();
|
||||
desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeRelocationImageViewDescriptor;
|
||||
@@ -120,6 +153,13 @@ namespace AZ
|
||||
|
||||
// probe classification image
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked)
|
||||
{
|
||||
// import the classification image now, since it is baked and therefore was not imported during the raytracing pass
|
||||
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(diffuseProbeGrid->GetClassificationImageAttachmentId(), diffuseProbeGrid->GetClassificationImage());
|
||||
AZ_Assert(result == RHI::ResultCode::Success, "Failed to import probeClassificationImage");
|
||||
}
|
||||
|
||||
RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = diffuseProbeGrid->GetClassificationImageAttachmentId();
|
||||
desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeClassificationImageViewDescriptor;
|
||||
@@ -127,6 +167,8 @@ namespace AZ
|
||||
|
||||
frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite);
|
||||
}
|
||||
|
||||
diffuseProbeGrid->GetTextureReadback().Update(GetName());
|
||||
}
|
||||
|
||||
Base::SetupFrameGraphDependencies(frameGraph);
|
||||
@@ -139,6 +181,12 @@ namespace AZ
|
||||
|
||||
for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetProbeGrids())
|
||||
{
|
||||
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::Baked &&
|
||||
!diffuseProbeGrid->HasValidBakedTextures())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs
|
||||
// (see ValidateSetImageView() of ShaderResourceGroupData.cpp)
|
||||
diffuseProbeGrid->UpdateRenderObjectSrg();
|
||||
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGridTextureReadBack.h>
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGrid.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
DiffuseProbeGridTextureReadback::DiffuseProbeGridTextureReadback(DiffuseProbeGrid* diffuseProbeGrid)
|
||||
: m_diffuseProbeGrid(diffuseProbeGrid)
|
||||
{
|
||||
}
|
||||
|
||||
void DiffuseProbeGridTextureReadback::BeginTextureReadback(DiffuseProbeGridBakeTexturesCallback callback)
|
||||
{
|
||||
AZ_Assert(m_readbackState == DiffuseProbeGridReadbackState::Idle, "DiffuseProbeGridTextureReadback is already processing a readback request");
|
||||
|
||||
m_callback = callback;
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Irradiance;
|
||||
}
|
||||
|
||||
void DiffuseProbeGridTextureReadback::Update(const AZ::Name& passName)
|
||||
{
|
||||
if (m_readbackState == DiffuseProbeGridReadbackState::Idle || m_readbackState == DiffuseProbeGridReadbackState::Complete)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_attachmentReadback.get() && m_attachmentReadback->GetReadbackState() > RPI::AttachmentReadback::ReadbackState::Idle)
|
||||
{
|
||||
// still processing previous request
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string readbackName = AZStd::string::format("DiffuseProbeGridReadback_%s", passName.GetCStr());
|
||||
RHI::ImageDescriptor descriptor;
|
||||
RHI::AttachmentId attachmentId;
|
||||
RPI::AttachmentReadback::CallbackFunction callbackFunction;
|
||||
|
||||
switch (m_readbackState)
|
||||
{
|
||||
case DiffuseProbeGridReadbackState::Irradiance:
|
||||
descriptor = m_diffuseProbeGrid->GetIrradianceImage()->GetDescriptor();
|
||||
attachmentId = m_diffuseProbeGrid->GetIrradianceImageAttachmentId();
|
||||
callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
m_irradianceReadbackResult = readbackResult;
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Distance;
|
||||
};
|
||||
break;
|
||||
case DiffuseProbeGridReadbackState::Distance:
|
||||
descriptor = m_diffuseProbeGrid->GetDistanceImage()->GetDescriptor();
|
||||
attachmentId = m_diffuseProbeGrid->GetDistanceImageAttachmentId();
|
||||
callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
m_distanceReadbackResult = readbackResult;
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Relocation;
|
||||
};
|
||||
break;
|
||||
case DiffuseProbeGridReadbackState::Relocation:
|
||||
descriptor = m_diffuseProbeGrid->GetRelocationImage()->GetDescriptor();
|
||||
attachmentId = m_diffuseProbeGrid->GetRelocationImageAttachmentId();
|
||||
callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
m_relocationReadbackResult = readbackResult;
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Classification;
|
||||
};
|
||||
break;
|
||||
case DiffuseProbeGridReadbackState::Classification:
|
||||
descriptor = m_diffuseProbeGrid->GetClassificationImage()->GetDescriptor();
|
||||
attachmentId = m_diffuseProbeGrid->GetClassificationImageAttachmentId();
|
||||
callbackFunction = [this](const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
{
|
||||
m_classificationReadbackResult = readbackResult;
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Complete;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Unknown readback state");
|
||||
}
|
||||
|
||||
m_attachmentReadback = AZStd::make_shared<AZ::RPI::AttachmentReadback>(AZ::RHI::ScopeId{ "DiffuseProbeGridTextureReadBack" });
|
||||
m_attachmentReadback->SetCallback(callbackFunction);
|
||||
|
||||
AZ::RPI::PassAttachment passAttachment;
|
||||
passAttachment.m_descriptor = descriptor;
|
||||
passAttachment.m_path = attachmentId;
|
||||
passAttachment.m_name = readbackName;
|
||||
passAttachment.m_lifetime = RHI::AttachmentLifetimeType::Imported;
|
||||
|
||||
m_attachmentReadback->ReadPassAttachment(&passAttachment, AZ::Name(readbackName));
|
||||
}
|
||||
|
||||
void DiffuseProbeGridTextureReadback::FrameBegin(AZ::RPI::Pass::FramePrepareParams& params)
|
||||
{
|
||||
if (m_readbackState == DiffuseProbeGridReadbackState::Idle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_attachmentReadback.get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_readbackState == DiffuseProbeGridReadbackState::Complete)
|
||||
{
|
||||
// readback of all textures is complete, invoke callback and return to Idle state
|
||||
m_callback(
|
||||
{ m_irradianceReadbackResult.m_dataBuffer, m_irradianceReadbackResult.m_imageDescriptor.m_format, m_irradianceReadbackResult.m_imageDescriptor.m_size },
|
||||
{ m_distanceReadbackResult.m_dataBuffer, m_distanceReadbackResult.m_imageDescriptor.m_format, m_distanceReadbackResult.m_imageDescriptor.m_size },
|
||||
{ m_relocationReadbackResult.m_dataBuffer, m_relocationReadbackResult.m_imageDescriptor.m_format, m_relocationReadbackResult.m_imageDescriptor.m_size },
|
||||
{ m_classificationReadbackResult.m_dataBuffer, m_classificationReadbackResult.m_imageDescriptor.m_format, m_classificationReadbackResult.m_imageDescriptor.m_size });
|
||||
|
||||
m_readbackState = DiffuseProbeGridReadbackState::Idle;
|
||||
m_attachmentReadback.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
m_attachmentReadback->FrameBegin(params);
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/ScopeProducer.h>
|
||||
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
|
||||
#include <Atom/RPI.Public/Pass/Pass.h>
|
||||
#include <Atom/Feature/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessorInterface.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
class DiffuseProbeGrid;
|
||||
|
||||
enum class DiffuseProbeGridReadbackState
|
||||
{
|
||||
Idle,
|
||||
Irradiance,
|
||||
Distance,
|
||||
Relocation,
|
||||
Classification,
|
||||
Complete
|
||||
};
|
||||
|
||||
//! This class contains functionality necessary to read back the DiffuseProbeGrid textures, which
|
||||
//! allows them to be saved as assets to run the DiffuseProbeGrid in non-realtime mode.
|
||||
class DiffuseProbeGridTextureReadback final
|
||||
{
|
||||
public:
|
||||
DiffuseProbeGridTextureReadback(DiffuseProbeGrid* diffuseProbeGrid);
|
||||
~DiffuseProbeGridTextureReadback() = default;
|
||||
|
||||
void BeginTextureReadback(DiffuseProbeGridBakeTexturesCallback callback);
|
||||
void Update(const AZ::Name& passName);
|
||||
void FrameBegin(AZ::RPI::Pass::FramePrepareParams& params);
|
||||
|
||||
private:
|
||||
|
||||
DiffuseProbeGrid* m_diffuseProbeGrid = nullptr;
|
||||
DiffuseProbeGridReadbackState m_readbackState = DiffuseProbeGridReadbackState::Idle;
|
||||
AZStd::shared_ptr<AZ::RPI::AttachmentReadback> m_attachmentReadback;
|
||||
DiffuseProbeGridBakeTexturesCallback m_callback;
|
||||
|
||||
AZ::RPI::AttachmentReadback::ReadbackResult m_irradianceReadbackResult;
|
||||
AZ::RPI::AttachmentReadback::ReadbackResult m_distanceReadbackResult;
|
||||
AZ::RPI::AttachmentReadback::ReadbackResult m_relocationReadbackResult;
|
||||
AZ::RPI::AttachmentReadback::ReadbackResult m_classificationReadbackResult;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -135,6 +135,8 @@ set(FILES
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGridRenderPass.h
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGrid.cpp
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGrid.h
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.cpp
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGridTextureReadback.h
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.h
|
||||
Source/DiffuseProbeGrid/DiffuseProbeGridFeatureProcessor.cpp
|
||||
Source/DisplayMapper/AcesOutputTransformPass.cpp
|
||||
|
||||
+157
-1
@@ -44,7 +44,17 @@ namespace AZ
|
||||
->Field("AmbientMultiplier", &DiffuseProbeGridComponentConfig::m_ambientMultiplier)
|
||||
->Field("ViewBias", &DiffuseProbeGridComponentConfig::m_viewBias)
|
||||
->Field("NormalBias", &DiffuseProbeGridComponentConfig::m_normalBias)
|
||||
;
|
||||
->Field("EditorMode", &DiffuseProbeGridComponentConfig::m_editorMode)
|
||||
->Field("RuntimeMode", &DiffuseProbeGridComponentConfig::m_runtimeMode)
|
||||
->Field("BakedIrradianceTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureRelativePath)
|
||||
->Field("BakedDistanceTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureRelativePath)
|
||||
->Field("BakedRelocationTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedRelocationTextureRelativePath)
|
||||
->Field("BakedClassificationTextureRelativePath", &DiffuseProbeGridComponentConfig::m_bakedClassificationTextureRelativePath)
|
||||
->Field("BakedIrradianceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureAsset)
|
||||
->Field("BakedDistanceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureAsset)
|
||||
->Field("BakedRelocationTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedRelocationTextureAsset)
|
||||
->Field("BakedClassificationTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedClassificationTextureAsset)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +120,26 @@ namespace AZ
|
||||
m_boxShapeInterface = LmbrCentral::BoxShapeComponentRequestsBus::FindFirstHandler(m_entityId);
|
||||
AZ_Assert(m_boxShapeInterface, "DiffuseProbeGridComponentController was unable to find box shape component");
|
||||
|
||||
// special handling is required if this component is being cloned in the editor:
|
||||
// check to see if the baked textures are already referenced by another DiffuseProbeGrid
|
||||
if (m_featureProcessor->AreBakedTexturesReferenced(
|
||||
m_configuration.m_bakedIrradianceTextureRelativePath,
|
||||
m_configuration.m_bakedDistanceTextureRelativePath,
|
||||
m_configuration.m_bakedRelocationTextureRelativePath,
|
||||
m_configuration.m_bakedClassificationTextureRelativePath))
|
||||
{
|
||||
// clear the baked texture paths and assets
|
||||
m_configuration.m_bakedIrradianceTextureRelativePath.clear();
|
||||
m_configuration.m_bakedDistanceTextureRelativePath.clear();
|
||||
m_configuration.m_bakedRelocationTextureRelativePath.clear();
|
||||
m_configuration.m_bakedClassificationTextureRelativePath.clear();
|
||||
|
||||
m_configuration.m_bakedIrradianceTextureAsset.Reset();
|
||||
m_configuration.m_bakedDistanceTextureAsset.Reset();
|
||||
m_configuration.m_bakedRelocationTextureAsset.Reset();
|
||||
m_configuration.m_bakedClassificationTextureAsset.Reset();
|
||||
}
|
||||
|
||||
// add this diffuse probe grid to the feature processor
|
||||
const AZ::Transform& transform = m_transformInterface->GetWorldTM();
|
||||
m_handle = m_featureProcessor->AddProbeGrid(transform, m_configuration.m_extents, m_configuration.m_probeSpacing);
|
||||
@@ -118,11 +148,61 @@ namespace AZ
|
||||
m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias);
|
||||
m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias);
|
||||
|
||||
// load the baked texture assets, but only if they are all valid
|
||||
if (m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() &&
|
||||
m_configuration.m_bakedDistanceTextureAsset.GetId().IsValid() &&
|
||||
m_configuration.m_bakedRelocationTextureAsset.GetId().IsValid() &&
|
||||
m_configuration.m_bakedClassificationTextureAsset.GetId().IsValid())
|
||||
{
|
||||
Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedIrradianceTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedDistanceTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedRelocationTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusConnect(m_configuration.m_bakedClassificationTextureAsset.GetId());
|
||||
|
||||
m_configuration.m_bakedIrradianceTextureAsset.QueueLoad();
|
||||
m_configuration.m_bakedDistanceTextureAsset.QueueLoad();
|
||||
m_configuration.m_bakedRelocationTextureAsset.QueueLoad();
|
||||
m_configuration.m_bakedClassificationTextureAsset.QueueLoad();
|
||||
}
|
||||
else if (m_configuration.m_runtimeMode == DiffuseProbeGridMode::Baked ||
|
||||
m_configuration.m_runtimeMode == DiffuseProbeGridMode::AutoSelect ||
|
||||
m_configuration.m_editorMode == DiffuseProbeGridMode::Baked ||
|
||||
m_configuration.m_editorMode == DiffuseProbeGridMode::AutoSelect)
|
||||
{
|
||||
AZ_Error("DiffuseProbeGrid", false, "DiffuseProbeGrid mdoe is set to Baked or Auto-Select, but it does not have baked texture assets. Please re-bake this DiffuseProbeGrid.");
|
||||
}
|
||||
|
||||
m_featureProcessor->SetMode(m_handle, m_configuration.m_runtimeMode);
|
||||
|
||||
// set box shape component dimensions from the configuration
|
||||
// this will invoke the OnShapeChanged() handler and set the outer extents on the feature processor
|
||||
m_boxShapeInterface->SetBoxDimensions(m_configuration.m_extents);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::OnAssetReady(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
// if all assets are ready we can set the baked texture images
|
||||
if (m_configuration.m_bakedIrradianceTextureAsset.IsReady() &&
|
||||
m_configuration.m_bakedDistanceTextureAsset.IsReady() &&
|
||||
m_configuration.m_bakedRelocationTextureAsset.IsReady() &&
|
||||
m_configuration.m_bakedClassificationTextureAsset.IsReady())
|
||||
{
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedIrradianceTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedDistanceTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedRelocationTextureAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(m_configuration.m_bakedClassificationTextureAsset.GetId());
|
||||
|
||||
UpdateBakedTextures();
|
||||
}
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::OnAssetError(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
Data::AssetBus::MultiHandler::BusDisconnect(asset.GetId());
|
||||
|
||||
AZ_Error("DiffuseProbeGrid", false, "Failed to load baked texture [%s], please re-bake this DiffuseProbeGrid.", asset.GetId().ToString<AZStd::string>().c_str());
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::Deactivate()
|
||||
{
|
||||
if (m_featureProcessor)
|
||||
@@ -212,20 +292,96 @@ namespace AZ
|
||||
|
||||
void DiffuseProbeGridComponentController::SetAmbientMultiplier(float ambientMultiplier)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_configuration.m_ambientMultiplier = ambientMultiplier;
|
||||
m_featureProcessor->SetAmbientMultiplier(m_handle, m_configuration.m_ambientMultiplier);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::SetViewBias(float viewBias)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_configuration.m_viewBias = viewBias;
|
||||
m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::SetNormalBias(float normalBias)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_configuration.m_normalBias = normalBias;
|
||||
m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::SetEditorMode(DiffuseProbeGridMode editorMode)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// update the configuration and change the DiffuseProbeGrid mode
|
||||
m_configuration.m_editorMode = editorMode;
|
||||
m_featureProcessor->SetMode(m_handle, m_configuration.m_editorMode);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::SetRuntimeMode(DiffuseProbeGridMode runtimeMode)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// only update the configuration
|
||||
m_configuration.m_runtimeMode = runtimeMode;
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::BakeTextures(DiffuseProbeGridBakeTexturesCallback callback)
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_featureProcessor->BakeTextures(
|
||||
m_handle,
|
||||
callback,
|
||||
m_configuration.m_bakedIrradianceTextureRelativePath,
|
||||
m_configuration.m_bakedDistanceTextureRelativePath,
|
||||
m_configuration.m_bakedRelocationTextureRelativePath,
|
||||
m_configuration.m_bakedClassificationTextureRelativePath);
|
||||
}
|
||||
|
||||
void DiffuseProbeGridComponentController::UpdateBakedTextures()
|
||||
{
|
||||
if (!m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DiffuseProbeGridBakedTextures bakedTextures;
|
||||
bakedTextures.m_irradianceImage = RPI::StreamingImage::FindOrCreate(m_configuration.m_bakedIrradianceTextureAsset);
|
||||
bakedTextures.m_irradianceImageRelativePath = m_configuration.m_bakedIrradianceTextureRelativePath;
|
||||
bakedTextures.m_distanceImage = RPI::StreamingImage::FindOrCreate(m_configuration.m_bakedDistanceTextureAsset);
|
||||
bakedTextures.m_distanceImageRelativePath = m_configuration.m_bakedDistanceTextureRelativePath;
|
||||
bakedTextures.m_relocationImageDescriptor = m_configuration.m_bakedRelocationTextureAsset->GetImageDescriptor();
|
||||
bakedTextures.m_relocationImageData = m_configuration.m_bakedRelocationTextureAsset->GetSubImageData(0, 0);
|
||||
bakedTextures.m_relocationImageRelativePath = m_configuration.m_bakedRelocationTextureRelativePath;
|
||||
bakedTextures.m_classificationImageDescriptor = m_configuration.m_bakedClassificationTextureAsset->GetImageDescriptor();
|
||||
bakedTextures.m_classificationImageData = m_configuration.m_bakedClassificationTextureAsset->GetSubImageData(0, 0);
|
||||
bakedTextures.m_classificationImageRelativePath = m_configuration.m_bakedClassificationTextureRelativePath;
|
||||
|
||||
m_featureProcessor->SetBakedTextures(m_handle, bakedTextures);
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+25
@@ -39,6 +39,19 @@ namespace AZ
|
||||
float m_ambientMultiplier = DefaultDiffuseProbeGridAmbientMultiplier;
|
||||
float m_viewBias = DefaultDiffuseProbeGridViewBias;
|
||||
float m_normalBias = DefaultDiffuseProbeGridNormalBias;
|
||||
|
||||
DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime;
|
||||
DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime;
|
||||
|
||||
AZStd::string m_bakedIrradianceTextureRelativePath;
|
||||
AZStd::string m_bakedDistanceTextureRelativePath;
|
||||
AZStd::string m_bakedRelocationTextureRelativePath;
|
||||
AZStd::string m_bakedClassificationTextureRelativePath;
|
||||
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedIrradianceTextureAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedDistanceTextureAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedRelocationTextureAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedClassificationTextureAsset;
|
||||
};
|
||||
|
||||
class DiffuseProbeGridComponentController final
|
||||
@@ -79,12 +92,24 @@ namespace AZ
|
||||
// ShapeComponentNotificationsBus overrides
|
||||
void OnShapeChanged(ShapeChangeReasons changeReason) override;
|
||||
|
||||
// AssetBus overrides
|
||||
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
|
||||
void OnAssetError(Data::Asset<Data::AssetData> asset) override;
|
||||
|
||||
// Property handlers
|
||||
bool ValidateProbeSpacing(const AZ::Vector3& newSpacing);
|
||||
void SetProbeSpacing(const AZ::Vector3& probeSpacing);
|
||||
void SetAmbientMultiplier(float ambientMultiplier);
|
||||
void SetViewBias(float viewBias);
|
||||
void SetNormalBias(float normalBias);
|
||||
void SetEditorMode(DiffuseProbeGridMode editorMode);
|
||||
void SetRuntimeMode(DiffuseProbeGridMode runtimeMode);
|
||||
|
||||
// Bake the diffuse probe grid textures to assets
|
||||
void BakeTextures(DiffuseProbeGridBakeTexturesCallback callback);
|
||||
|
||||
// Update the baked texture assets from the configuration
|
||||
void UpdateBakedTextures();
|
||||
|
||||
// box shape component, used for defining the outer extents of the probe area
|
||||
LmbrCentral::BoxShapeComponentRequests* m_boxShapeInterface = nullptr;
|
||||
|
||||
+333
-19
@@ -16,6 +16,15 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <Atom/RPI.Reflect/Image/StreamingImagePoolAsset.h>
|
||||
#include <Atom/Utils/DdsFile.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -35,7 +44,9 @@ namespace AZ
|
||||
->Field("ambientMultiplier", &EditorDiffuseProbeGridComponent::m_ambientMultiplier)
|
||||
->Field("viewBias", &EditorDiffuseProbeGridComponent::m_viewBias)
|
||||
->Field("normalBias", &EditorDiffuseProbeGridComponent::m_normalBias)
|
||||
;
|
||||
->Field("editorMode", &EditorDiffuseProbeGridComponent::m_editorMode)
|
||||
->Field("runtimeMode", &EditorDiffuseProbeGridComponent::m_runtimeMode)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
@@ -48,25 +59,26 @@ namespace AZ
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo<RPI::ModelAsset>::Uuid())
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Probe Spacing")
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Probe Spacing (meters between probes)")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingX, "X", "Probe spacing on the X-axis")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingX, "X", "Probe spacing on the X-axis, in meters")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateX)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingY, "Y", "Probe spacing on the Y-axis")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingY, "Y", "Probe spacing on the Y-axis, in meters")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateY)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingZ, "Z", "Probe spacing on the Z-axis")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorDiffuseProbeGridComponent::m_probeSpacingZ, "Z", "Probe spacing on the Z-axis, in meters")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnProbeSpacingValidateZ)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnProbeSpacingChanged)
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Grid Settings")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_ambientMultiplier, "Ambient Multiplier", "Multiplier for the irradiance intensity")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnAmbientMultiplierChanged)
|
||||
->Attribute(Edit::Attributes::Decimals, 0)
|
||||
->Attribute(Edit::Attributes::Step, 1.0f)
|
||||
->Attribute(Edit::Attributes::Decimals, 1)
|
||||
->Attribute(Edit::Attributes::Step, 0.1f)
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 10.0f)
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_viewBias, "View Bias", "View bias adjustment")
|
||||
@@ -81,6 +93,27 @@ namespace AZ
|
||||
->Attribute(Edit::Attributes::Step, 0.1f)
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 1.0f)
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "Grid mode")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_editorMode, "Editor Mode", "Controls whether the editor uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnEditorModeChanged)
|
||||
->EnumAttribute(DiffuseProbeGridMode::RealTime, "Real Time (Ray-Traced)")
|
||||
->EnumAttribute(DiffuseProbeGridMode::Baked, "Baked")
|
||||
->EnumAttribute(DiffuseProbeGridMode::AutoSelect, "Auto Select")
|
||||
->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_runtimeMode, "Runtime Mode", "Controls whether the runtime uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnRuntimeModeChanged)
|
||||
->EnumAttribute(DiffuseProbeGridMode::RealTime, "Real Time (Ray-Traced)")
|
||||
->EnumAttribute(DiffuseProbeGridMode::Baked, "Baked")
|
||||
->EnumAttribute(DiffuseProbeGridMode::AutoSelect, "Auto Select")
|
||||
->ClassElement(AZ::Edit::ClassElements::Group, "Bake Textures")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->UIElement(AZ::Edit::UIHandlers::Button, "Bake Textures", "Bake the Diffuse Probe Grid textures to static assets that will be used when the mode is set to Baked")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
|
||||
->Attribute(AZ::Edit::Attributes::ButtonText, "Bake Textures")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::BakeDiffuseProbeGrid)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorDiffuseProbeGridComponent::GetBakeDiffuseProbeGridVisibilitySetting)
|
||||
;
|
||||
|
||||
editContext->Class<DiffuseProbeGridComponentController>(
|
||||
@@ -90,12 +123,6 @@ namespace AZ
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &DiffuseProbeGridComponentController::m_configuration, "Configuration", "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
;
|
||||
|
||||
editContext->Class<DiffuseProbeGridComponentConfig>(
|
||||
"DiffuseProbeGridComponentConfig", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,15 +148,73 @@ namespace AZ
|
||||
BaseClass::Activate();
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void EditorDiffuseProbeGridComponent::Deactivate()
|
||||
{
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
|
||||
BaseClass::Deactivate();
|
||||
}
|
||||
|
||||
void EditorDiffuseProbeGridComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DiffuseProbeGridComponentConfig& configuration = m_controller.m_configuration;
|
||||
|
||||
// set the editor mode, which will override the runtime mode set by the controller
|
||||
if (!m_editorModeSet)
|
||||
{
|
||||
m_controller.m_featureProcessor->SetMode(m_controller.m_handle, configuration.m_editorMode);
|
||||
m_editorModeSet = true;
|
||||
}
|
||||
|
||||
CheckTextureAssetNotification(configuration.m_bakedIrradianceTextureRelativePath, configuration.m_bakedIrradianceTextureAsset);
|
||||
CheckTextureAssetNotification(configuration.m_bakedDistanceTextureRelativePath, configuration.m_bakedDistanceTextureAsset);
|
||||
CheckTextureAssetNotification(configuration.m_bakedRelocationTextureRelativePath, configuration.m_bakedRelocationTextureAsset);
|
||||
CheckTextureAssetNotification(configuration.m_bakedClassificationTextureRelativePath, configuration.m_bakedClassificationTextureAsset);
|
||||
}
|
||||
|
||||
void EditorDiffuseProbeGridComponent::CheckTextureAssetNotification(const AZStd::string& relativePath, Data::Asset<RPI::StreamingImageAsset>& configurationAsset)
|
||||
{
|
||||
Data::Asset<RPI::StreamingImageAsset> textureAsset;
|
||||
DiffuseProbeGridTextureNotificationType notificationType = DiffuseProbeGridTextureNotificationType::None;
|
||||
if (m_controller.m_featureProcessor->CheckTextureAssetNotification(relativePath + ".streamingimage", textureAsset, notificationType))
|
||||
{
|
||||
if (notificationType == DiffuseProbeGridTextureNotificationType::Ready)
|
||||
{
|
||||
// bake is complete, update configuration with the new baked texture asset
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("DiffuseProbeGrid Texture Bake");
|
||||
configurationAsset = { textureAsset.GetAs<RPI::StreamingImageAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
SetDirty();
|
||||
|
||||
if (m_controller.m_configuration.m_bakedIrradianceTextureAsset.IsReady() &&
|
||||
m_controller.m_configuration.m_bakedDistanceTextureAsset.IsReady() &&
|
||||
m_controller.m_configuration.m_bakedClassificationTextureAsset.IsReady() &&
|
||||
m_controller.m_configuration.m_bakedRelocationTextureAsset.IsReady())
|
||||
{
|
||||
m_controller.UpdateBakedTextures();
|
||||
}
|
||||
}
|
||||
else if (notificationType == DiffuseProbeGridTextureNotificationType::Error)
|
||||
{
|
||||
QMessageBox::information(
|
||||
QApplication::activeWindow(),
|
||||
"Diffuse Probe Grid",
|
||||
"Diffuse Probe Grid texture failed to bake, please check the Asset Processor for more information.",
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Aabb EditorDiffuseProbeGridComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
|
||||
{
|
||||
return m_controller.GetAabb();
|
||||
@@ -140,11 +225,19 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditorDiffuseProbeGridComponent::OnEntityInfoUpdatedVisibility(AZ::EntityId entityId, bool visible)
|
||||
{
|
||||
if ((GetEntityId() == entityId) && !visible)
|
||||
{
|
||||
m_editorModeSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> EditorDiffuseProbeGridComponent::OnProbeSpacingValidateX(void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again"));
|
||||
return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing."));
|
||||
}
|
||||
|
||||
float newProbeSpacingX = *(reinterpret_cast<float*>(newValue));
|
||||
@@ -152,7 +245,7 @@ namespace AZ
|
||||
Vector3 newSpacing(newProbeSpacingX, m_probeSpacingY, m_probeSpacingZ);
|
||||
if (!m_controller.ValidateProbeSpacing(newSpacing))
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents"));
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents."));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
@@ -162,7 +255,7 @@ namespace AZ
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again"));
|
||||
return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing."));
|
||||
}
|
||||
|
||||
float newProbeSpacingY = *(reinterpret_cast<float*>(newValue));
|
||||
@@ -170,7 +263,7 @@ namespace AZ
|
||||
Vector3 newSpacing(m_probeSpacingX, newProbeSpacingY, m_probeSpacingZ);
|
||||
if (!m_controller.ValidateProbeSpacing(newSpacing))
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents"));
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents."));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
@@ -180,7 +273,7 @@ namespace AZ
|
||||
{
|
||||
if (!m_controller.m_featureProcessor)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Unable to adjust probe spacing, please try again"));
|
||||
return AZ::Failure(AZStd::string("This Diffuse Probe Grid entity is hidden, it must be visible in order to change the probe spacing."));
|
||||
}
|
||||
|
||||
float newProbeSpacingZ = *(reinterpret_cast<float*>(newValue));
|
||||
@@ -188,7 +281,7 @@ namespace AZ
|
||||
Vector3 newSpacing(m_probeSpacingX, m_probeSpacingY, newProbeSpacingZ);
|
||||
if (!m_controller.ValidateProbeSpacing(newSpacing))
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents"));
|
||||
return AZ::Failure(AZStd::string("Probe spacing exceeds max allowable grid size with current extents."));
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
@@ -218,5 +311,226 @@ namespace AZ
|
||||
m_controller.SetNormalBias(m_normalBias);
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZ::u32 EditorDiffuseProbeGridComponent::OnEditorModeChanged()
|
||||
{
|
||||
// this will update the configuration and also change the DiffuseProbeGrid mode
|
||||
m_controller.SetEditorMode(m_editorMode);
|
||||
return AZ::Edit::PropertyRefreshLevels::EntireTree;
|
||||
}
|
||||
|
||||
AZ::u32 EditorDiffuseProbeGridComponent::OnRuntimeModeChanged()
|
||||
{
|
||||
// this will only update the configuration
|
||||
m_controller.SetRuntimeMode(m_runtimeMode);
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> EditorDiffuseProbeGridComponent::OnModeChangeValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
|
||||
{
|
||||
DiffuseProbeGridMode newMode = (*(reinterpret_cast<DiffuseProbeGridMode*>(newValue)));
|
||||
|
||||
if (newMode == DiffuseProbeGridMode::Baked || newMode == DiffuseProbeGridMode::AutoSelect)
|
||||
{
|
||||
if (!m_controller.m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() ||
|
||||
!m_controller.m_configuration.m_bakedDistanceTextureAsset.GetId().IsValid() ||
|
||||
!m_controller.m_configuration.m_bakedRelocationTextureAsset.GetId().IsValid() ||
|
||||
!m_controller.m_configuration.m_bakedClassificationTextureAsset.GetId().IsValid())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Please bake textures before changing the Diffuse Probe Grid to Baked or Auto-Select mode."));
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::u32 EditorDiffuseProbeGridComponent::GetBakeDiffuseProbeGridVisibilitySetting()
|
||||
{
|
||||
// the Bake button is visible only when the editor mode is set to RealTime
|
||||
return m_editorMode == DiffuseProbeGridMode::RealTime ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
|
||||
}
|
||||
|
||||
AZ::u32 EditorDiffuseProbeGridComponent::BakeDiffuseProbeGrid()
|
||||
{
|
||||
if (m_bakeInProgress)
|
||||
{
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
// retrieve entity visibility
|
||||
bool isHidden = false;
|
||||
AzToolsFramework::EditorEntityInfoRequestBus::EventResult(
|
||||
isHidden,
|
||||
GetEntityId(),
|
||||
&AzToolsFramework::EditorEntityInfoRequestBus::Events::IsHidden);
|
||||
|
||||
// the entity must be visible in order to bake
|
||||
if (isHidden)
|
||||
{
|
||||
QMessageBox::information(
|
||||
QApplication::activeWindow(),
|
||||
"Diffuse Probe Grid",
|
||||
"This Diffuse Probe Grid entity is hidden, it must be visible in order to bake textures.",
|
||||
QMessageBox::Ok);
|
||||
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
DiffuseProbeGridComponentConfig& configuration = m_controller.m_configuration;
|
||||
|
||||
// retrieve the source image paths from the configuration
|
||||
// Note: we need to make sure to use the same source image for each bake
|
||||
AZStd::string irradianceTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedIrradianceTextureRelativePath, DiffuseProbeGridIrradianceFileName);
|
||||
AZStd::string distanceTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedDistanceTextureRelativePath, DiffuseProbeGridDistanceFileName);
|
||||
AZStd::string relocationTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedRelocationTextureRelativePath, DiffuseProbeGridRelocationFileName);
|
||||
AZStd::string classificationTextureRelativePath = ValidateOrCreateNewTexturePath(configuration.m_bakedClassificationTextureRelativePath, DiffuseProbeGridClassificationFileName);
|
||||
|
||||
// create the full paths
|
||||
char projectPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
AZStd::string irradianceTextureFullPath;
|
||||
AzFramework::StringFunc::Path::Join(projectPath, irradianceTextureRelativePath.c_str(), irradianceTextureFullPath, true, true);
|
||||
AZStd::string distanceTextureFullPath;
|
||||
AzFramework::StringFunc::Path::Join(projectPath, distanceTextureRelativePath.c_str(), distanceTextureFullPath, true, true);
|
||||
AZStd::string relocationTextureFullPath;
|
||||
AzFramework::StringFunc::Path::Join(projectPath, relocationTextureRelativePath.c_str(), relocationTextureFullPath, true, true);
|
||||
AZStd::string classificationTextureFullPath;
|
||||
AzFramework::StringFunc::Path::Join(projectPath, classificationTextureRelativePath.c_str(), classificationTextureFullPath, true, true);
|
||||
|
||||
// make sure the folder is created
|
||||
AZStd::string diffuseProbeGridFolder;
|
||||
AzFramework::StringFunc::Path::GetFolderPath(irradianceTextureFullPath.data(), diffuseProbeGridFolder);
|
||||
AZ::IO::SystemFile::CreateDir(diffuseProbeGridFolder.c_str());
|
||||
|
||||
// check out the files in source control
|
||||
CheckoutSourceTextureFile(irradianceTextureFullPath);
|
||||
CheckoutSourceTextureFile(distanceTextureFullPath);
|
||||
CheckoutSourceTextureFile(relocationTextureFullPath);
|
||||
CheckoutSourceTextureFile(classificationTextureFullPath);
|
||||
|
||||
// update the configuration
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("DiffuseProbeGrid bake");
|
||||
configuration.m_bakedIrradianceTextureRelativePath = irradianceTextureRelativePath;
|
||||
configuration.m_bakedDistanceTextureRelativePath = distanceTextureRelativePath;
|
||||
configuration.m_bakedRelocationTextureRelativePath = relocationTextureRelativePath;
|
||||
configuration.m_bakedClassificationTextureRelativePath = classificationTextureRelativePath;
|
||||
SetDirty();
|
||||
|
||||
// callback for the texture readback
|
||||
DiffuseProbeGridBakeTexturesCallback bakeTexturesCallback = [=](
|
||||
DiffuseProbeGridTexture irradianceTexture,
|
||||
DiffuseProbeGridTexture distanceTexture,
|
||||
DiffuseProbeGridTexture relocationTexture,
|
||||
DiffuseProbeGridTexture classificationTexture)
|
||||
{
|
||||
// irradiance
|
||||
{
|
||||
AZ::DdsFile::DdsFileData fileData = { irradianceTexture.m_size, irradianceTexture.m_format, irradianceTexture.m_data.get() };
|
||||
[[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(irradianceTextureFullPath, fileData);
|
||||
AZ_Assert(outcome.IsSuccess(), "Failed to write Irradiance texture .dds file [%s]", irradianceTextureFullPath.c_str());
|
||||
}
|
||||
|
||||
// distance
|
||||
{
|
||||
AZ::DdsFile::DdsFileData fileData = { distanceTexture.m_size, distanceTexture.m_format, distanceTexture.m_data.get() };
|
||||
[[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(distanceTextureFullPath, fileData);
|
||||
AZ_Assert(outcome.IsSuccess(), "Failed to write Distance texture .dds file [%s]", distanceTextureFullPath.c_str());
|
||||
}
|
||||
|
||||
// relocation
|
||||
{
|
||||
AZ::DdsFile::DdsFileData fileData = { relocationTexture.m_size, relocationTexture.m_format, relocationTexture.m_data.get() };
|
||||
[[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(relocationTextureFullPath, fileData);
|
||||
AZ_Assert(outcome.IsSuccess(), "Failed to write Relocation texture .dds file [%s]", relocationTextureFullPath.c_str());
|
||||
}
|
||||
|
||||
// classification
|
||||
{
|
||||
AZ::DdsFile::DdsFileData fileData = { classificationTexture.m_size, classificationTexture.m_format, classificationTexture.m_data.get() };
|
||||
[[maybe_unused]] const auto outcome = AZ::DdsFile::WriteFile(classificationTextureFullPath, fileData);
|
||||
AZ_Assert(outcome.IsSuccess(), "Failed to write Classification texture .dds file [%s]", classificationTextureFullPath.c_str());
|
||||
}
|
||||
|
||||
m_bakeInProgress = false;
|
||||
};
|
||||
|
||||
m_bakeInProgress = true;
|
||||
m_controller.BakeTextures(bakeTexturesCallback);
|
||||
|
||||
while (m_bakeInProgress)
|
||||
{
|
||||
QApplication::processEvents();
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
QMessageBox::information(
|
||||
QApplication::activeWindow(),
|
||||
"Diffuse Probe Grid",
|
||||
"Successfully baked Diffuse Probe Grid textures.",
|
||||
QMessageBox::Ok);
|
||||
|
||||
return AZ::Edit::PropertyRefreshLevels::None;
|
||||
}
|
||||
|
||||
AZStd::string EditorDiffuseProbeGridComponent::ValidateOrCreateNewTexturePath(const AZStd::string& configurationRelativePath, const char* fileSuffix)
|
||||
{
|
||||
AZStd::string relativePath = configurationRelativePath;
|
||||
AZStd::string fullPath;
|
||||
|
||||
char projectPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
if (!relativePath.empty())
|
||||
{
|
||||
// test to see if the texture file is actually there, if it was removed we need to
|
||||
// generate a new filename, otherwise it will cause an error in the asset system
|
||||
AzFramework::StringFunc::Path::Join(projectPath, configurationRelativePath.c_str(), fullPath, true, true);
|
||||
|
||||
if (!AZ::IO::FileIOBase::GetInstance()->Exists(fullPath.c_str()))
|
||||
{
|
||||
// file does not exist, clear the relative path so we generate a new name
|
||||
relativePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// build a new image path if necessary
|
||||
if (relativePath.empty())
|
||||
{
|
||||
// the file name is a combination of the entity name, a UUID, and the filemask
|
||||
Entity* entity = GetEntity();
|
||||
AZ_Assert(entity, "DiffuseProbeGrid entity is null");
|
||||
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
relativePath = "DiffuseProbeGrids/" + entity->GetName() + uuidString + fileSuffix;
|
||||
|
||||
// replace any invalid filename characters
|
||||
auto invalidCharacters = [](char letter)
|
||||
{
|
||||
return
|
||||
letter == ':' || letter == '"' || letter == '\'' ||
|
||||
letter == '{' || letter == '}' ||
|
||||
letter == '<' || letter == '>';
|
||||
};
|
||||
AZStd::replace_if(relativePath.begin(), relativePath.end(), invalidCharacters, '_');
|
||||
}
|
||||
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
void EditorDiffuseProbeGridComponent::CheckoutSourceTextureFile(const AZStd::string& fullPath)
|
||||
{
|
||||
bool checkedOutSuccessfully = false;
|
||||
using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus;
|
||||
ApplicationBus::BroadcastResult(
|
||||
checkedOutSuccessfully,
|
||||
&ApplicationBus::Events::RequestEditForFileBlocking,
|
||||
fullPath.c_str(),
|
||||
"Checking out for edit...",
|
||||
ApplicationBus::Events::RequestEditProgressCallback());
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+29
@@ -12,8 +12,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGridComponent.h>
|
||||
#include <DiffuseProbeGrid/DiffuseProbeGridComponentConstants.h>
|
||||
#include <Atom/Feature/Utils/EditorRenderComponentAdapter.h>
|
||||
@@ -26,6 +28,8 @@ namespace AZ
|
||||
: public EditorRenderComponentAdapter<DiffuseProbeGridComponentController, DiffuseProbeGridComponent, DiffuseProbeGridComponentConfig>
|
||||
, private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler
|
||||
, private AzFramework::EntityDebugDisplayEventBus::Handler
|
||||
, private AZ::TickBus::Handler
|
||||
, private AzToolsFramework::EditorEntityInfoNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
using BaseClass = EditorRenderComponentAdapter<DiffuseProbeGridComponentController, DiffuseProbeGridComponent, DiffuseProbeGridComponentConfig>;
|
||||
@@ -41,10 +45,22 @@ namespace AZ
|
||||
void Deactivate() override;
|
||||
|
||||
private:
|
||||
|
||||
// AZ::TickBus overrides
|
||||
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
|
||||
|
||||
// EditorComponentSelectionRequestsBus overrides
|
||||
AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override;
|
||||
bool SupportsEditorRayIntersect() override;
|
||||
|
||||
// EditorEntityInfoNotifications overrides
|
||||
void OnEntityInfoUpdatedVisibility(AZ::EntityId entityId, bool visible) override;
|
||||
|
||||
// helper functions
|
||||
AZStd::string ValidateOrCreateNewTexturePath(const AZStd::string& relativePath, const char* fileSuffix);
|
||||
void CheckoutSourceTextureFile(const AZStd::string& fullPath);
|
||||
void CheckTextureAssetNotification(const AZStd::string& relativePath, Data::Asset<RPI::StreamingImageAsset>& configurationAsset);
|
||||
|
||||
// property change notifications
|
||||
AZ::Outcome<void, AZStd::string> OnProbeSpacingValidateX(void* newValue, const AZ::Uuid& valueType);
|
||||
AZ::Outcome<void, AZStd::string> OnProbeSpacingValidateY(void* newValue, const AZ::Uuid& valueType);
|
||||
@@ -53,6 +69,13 @@ namespace AZ
|
||||
AZ::u32 OnAmbientMultiplierChanged();
|
||||
AZ::u32 OnViewBiasChanged();
|
||||
AZ::u32 OnNormalBiasChanged();
|
||||
AZ::u32 OnEditorModeChanged();
|
||||
AZ::u32 OnRuntimeModeChanged();
|
||||
AZ::Outcome<void, AZStd::string> OnModeChangeValidate(void* newValue, const AZ::Uuid& valueType);
|
||||
|
||||
// Button handler
|
||||
AZ::u32 BakeDiffuseProbeGrid();
|
||||
AZ::u32 GetBakeDiffuseProbeGridVisibilitySetting();
|
||||
|
||||
// properties
|
||||
float m_probeSpacingX = DefaultDiffuseProbeGridSpacing;
|
||||
@@ -61,6 +84,12 @@ namespace AZ
|
||||
float m_ambientMultiplier = DefaultDiffuseProbeGridAmbientMultiplier;
|
||||
float m_viewBias = DefaultDiffuseProbeGridViewBias;
|
||||
float m_normalBias = DefaultDiffuseProbeGridNormalBias;
|
||||
DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime;
|
||||
DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime;
|
||||
|
||||
// flags
|
||||
bool m_editorModeSet = false;
|
||||
AZStd::atomic_bool m_bakeInProgress = false;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
Reference in New Issue
Block a user