3
0

ReflectionScreenSpaceBlurPass.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "ReflectionScreenSpaceBlurPass.h"
  9. #include "ReflectionScreenSpaceBlurChildPass.h"
  10. #include <Atom/RHI/FrameGraphBuilder.h>
  11. #include <Atom/RHI/FrameGraphAttachmentInterface.h>
  12. #include <Atom/RHI.Reflect/ImageViewDescriptor.h>
  13. #include <Atom/RPI.Reflect/Pass/FullscreenTrianglePassData.h>
  14. #include <Atom/RPI.Reflect/Pass/PassName.h>
  15. #include <Atom/RPI.Public/Pass/PassDefines.h>
  16. #include <Atom/RPI.Public/Pass/PassFactory.h>
  17. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  18. #include <Atom/RPI.Public/Pass/PassUtils.h>
  19. #include <Atom/RPI.Public/RenderPipeline.h>
  20. #include <Atom/RPI.Public/RPIUtils.h>
  21. #include <Atom/RPI.Reflect/Pass/PassRequest.h>
  22. #include <Atom/RPI.Public/Pass/PassFilter.h>
  23. #include <Atom/RPI.Public/Image/ImageSystemInterface.h>
  24. #include <Atom/RPI.Public/Image/AttachmentImagePool.h>
  25. namespace AZ
  26. {
  27. namespace Render
  28. {
  29. RPI::Ptr<ReflectionScreenSpaceBlurPass> ReflectionScreenSpaceBlurPass::Create(const RPI::PassDescriptor& descriptor)
  30. {
  31. RPI::Ptr<ReflectionScreenSpaceBlurPass> pass = aznew ReflectionScreenSpaceBlurPass(descriptor);
  32. return AZStd::move(pass);
  33. }
  34. ReflectionScreenSpaceBlurPass::ReflectionScreenSpaceBlurPass(const RPI::PassDescriptor& descriptor)
  35. : RPI::ParentPass(descriptor)
  36. {
  37. }
  38. void ReflectionScreenSpaceBlurPass::ResetInternal()
  39. {
  40. RemoveChildren();
  41. }
  42. void ReflectionScreenSpaceBlurPass::CreateChildPassesInternal()
  43. {
  44. RPI::PassSystemInterface* passSystem = RPI::PassSystemInterface::Get();
  45. m_verticalBlurChildPasses.clear();
  46. m_horizontalBlurChildPasses.clear();
  47. // load shaders
  48. constexpr const char* verticalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurVertical.azshader";
  49. Data::Instance<AZ::RPI::Shader> verticalBlurShader = RPI::LoadCriticalShader(verticalBlurShaderFilePath);
  50. if (verticalBlurShader == nullptr)
  51. {
  52. AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), verticalBlurShaderFilePath);
  53. return;
  54. }
  55. constexpr const char* horizontalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.azshader";
  56. Data::Instance<AZ::RPI::Shader> horizontalBlurShader = RPI::LoadCriticalShader(horizontalBlurShaderFilePath);
  57. if (horizontalBlurShader == nullptr)
  58. {
  59. AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), horizontalBlurShaderFilePath);
  60. return;
  61. }
  62. // load pass templates
  63. const AZStd::shared_ptr<const RPI::PassTemplate> blurVerticalPassTemplate = RPI::PassSystemInterface::Get()->GetPassTemplate(Name("ReflectionScreenSpaceBlurVerticalPassTemplate"));
  64. const AZStd::shared_ptr<const RPI::PassTemplate> blurHorizontalPassTemplate = RPI::PassSystemInterface::Get()->GetPassTemplate(Name("ReflectionScreenSpaceBlurHorizontalPassTemplate"));
  65. // create pass descriptors
  66. RPI::PassDescriptor verticalBlurChildDesc;
  67. verticalBlurChildDesc.m_passTemplate = blurVerticalPassTemplate;
  68. RPI::PassDescriptor horizontalBlurChildDesc;
  69. horizontalBlurChildDesc.m_passTemplate = blurHorizontalPassTemplate;
  70. // add child passes to perform the vertical and horizontal Gaussian blur for each roughness mip level
  71. for (uint32_t mip = 0; mip < m_mipLevels - 1; ++mip)
  72. {
  73. // create Vertical blur child passes
  74. {
  75. AZStd::string verticalBlurChildPassName = AZStd::string::format("ReflectionScreenSpace_VerticalMipBlur%d", mip + 1);
  76. verticalBlurChildDesc.m_passName = Name(verticalBlurChildPassName);
  77. RPI::Ptr<Render::ReflectionScreenSpaceBlurChildPass> verticalBlurChildPass = passSystem->CreatePass<Render::ReflectionScreenSpaceBlurChildPass>(verticalBlurChildDesc);
  78. verticalBlurChildPass->SetType(Render::ReflectionScreenSpaceBlurChildPass::PassType::Vertical);
  79. verticalBlurChildPass->SetMipLevel(mip + 1);
  80. m_verticalBlurChildPasses.push_back(verticalBlurChildPass);
  81. AddChild(verticalBlurChildPass);
  82. }
  83. // create Horizontal blur child passes
  84. {
  85. AZStd::string horizontalBlurChildPassName = AZStd::string::format("ReflectionScreenSpace_HorizonalMipBlur%d", mip + 1);
  86. horizontalBlurChildDesc.m_passName = Name(horizontalBlurChildPassName);
  87. RPI::Ptr<Render::ReflectionScreenSpaceBlurChildPass> horizontalBlurChildPass = passSystem->CreatePass<Render::ReflectionScreenSpaceBlurChildPass>(horizontalBlurChildDesc);
  88. horizontalBlurChildPass->SetType(Render::ReflectionScreenSpaceBlurChildPass::PassType::Horizontal);
  89. horizontalBlurChildPass->SetMipLevel(mip + 1);
  90. m_horizontalBlurChildPasses.push_back(horizontalBlurChildPass);
  91. AddChild(horizontalBlurChildPass);
  92. }
  93. }
  94. }
  95. void ReflectionScreenSpaceBlurPass::BuildInternal()
  96. {
  97. RemoveChildren();
  98. m_flags.m_createChildren = true;
  99. // retrieve the reflection attachment
  100. RPI::PassAttachment* reflectionImageAttachment = GetInputOutputBinding(0).GetAttachment().get();
  101. m_imageSize = reflectionImageAttachment->m_descriptor.m_image.m_size;
  102. m_mipLevels = aznumeric_cast<uint32_t>(reflectionImageAttachment->m_descriptor.m_image.m_mipLevels);
  103. // create transient attachments, one for each blur mip level
  104. AZStd::vector<RPI::PassAttachment*> transientPassAttachments;
  105. for (uint32_t mip = 1; mip <= m_mipLevels - 1; ++mip)
  106. {
  107. RHI::Size mipSize = m_imageSize.GetReducedMip(mip);
  108. RHI::ImageBindFlags imageBindFlags = RHI::ImageBindFlags::Color | RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead;
  109. auto transientImageDesc = RHI::ImageDescriptor::Create2D(imageBindFlags, mipSize.m_width, mipSize.m_height, RHI::Format::R16G16B16A16_FLOAT);
  110. RPI::PassAttachment* transientPassAttachment = aznew RPI::PassAttachment();
  111. AZStd::string transientAttachmentName = AZStd::string::format("%s.ReflectionScreenSpace_BlurImage%d", GetPathName().GetCStr(), mip);
  112. transientPassAttachment->m_name = transientAttachmentName;
  113. transientPassAttachment->m_path = transientAttachmentName;
  114. transientPassAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient;
  115. transientPassAttachment->m_descriptor = transientImageDesc;
  116. transientPassAttachments.push_back(transientPassAttachment);
  117. m_ownedAttachments.push_back(transientPassAttachment);
  118. }
  119. // call ParentPass::BuildInternal() first to configure the slots and auto-add the empty bindings,
  120. // then we will assign attachments to the bindings
  121. ParentPass::BuildInternal();
  122. // setup attachment bindings on vertical blur child passes
  123. uint32_t attachmentIndex = 0;
  124. for (auto& verticalBlurChildPass : m_verticalBlurChildPasses)
  125. {
  126. // mip0 source input
  127. RPI::PassAttachmentBinding& inputAttachmentBinding = verticalBlurChildPass->GetInputBinding(0);
  128. inputAttachmentBinding.SetAttachment(reflectionImageAttachment);
  129. inputAttachmentBinding.m_connectedBinding = &GetInputOutputBinding(0);
  130. // mipN transient output
  131. RPI::PassAttachmentBinding& outputAttachmentBinding = verticalBlurChildPass->GetOutputBinding(0);
  132. outputAttachmentBinding.SetAttachment(transientPassAttachments[attachmentIndex]);
  133. verticalBlurChildPass->UpdateConnectedBindings();
  134. attachmentIndex++;
  135. }
  136. // setup attachment bindings on horizontal blur child passes
  137. attachmentIndex = 0;
  138. for (auto& horizontalBlurChildPass : m_horizontalBlurChildPasses)
  139. {
  140. RPI::PassAttachmentBinding& inputAttachmentBinding = horizontalBlurChildPass->GetInputBinding(0);
  141. inputAttachmentBinding.SetAttachment(transientPassAttachments[attachmentIndex]);
  142. inputAttachmentBinding.m_connectedBinding = &m_verticalBlurChildPasses[attachmentIndex]->GetOutputBinding(0);
  143. RPI::PassAttachmentBinding& outputAttachmentBinding = horizontalBlurChildPass->GetOutputBinding(0);
  144. uint32_t mipLevel = attachmentIndex + 1;
  145. RHI::ImageViewDescriptor outputViewDesc;
  146. outputViewDesc.m_mipSliceMin = static_cast<int16_t>(mipLevel);
  147. outputViewDesc.m_mipSliceMax = static_cast<int16_t>(mipLevel);
  148. outputAttachmentBinding.m_unifiedScopeDesc.SetAsImage(outputViewDesc);
  149. outputAttachmentBinding.SetAttachment(reflectionImageAttachment);
  150. horizontalBlurChildPass->UpdateConnectedBindings();
  151. attachmentIndex++;
  152. }
  153. }
  154. void ReflectionScreenSpaceBlurPass::FrameBeginInternal(FramePrepareParams params)
  155. {
  156. // get input attachment size
  157. RPI::PassAttachment* inputAttachment = GetInputOutputBinding(0).GetAttachment().get();
  158. AZ_Assert(inputAttachment, "ReflectionScreenSpaceBlurChildPass: Input binding has no attachment!");
  159. RHI::Size size = inputAttachment->m_descriptor.m_image.m_size;
  160. if (m_imageSize != size)
  161. {
  162. m_imageSize = size;
  163. uint32_t mip = 1;
  164. for (auto& ownedAttachment : m_ownedAttachments)
  165. {
  166. RHI::Size mipSize = m_imageSize.GetReducedMip(mip);
  167. ownedAttachment->m_descriptor.m_image.m_size = mipSize;
  168. mip++;
  169. }
  170. }
  171. ParentPass::FrameBeginInternal(params);
  172. }
  173. } // namespace RPI
  174. } // namespace AZ