SpecularReflectionsFeatureProcessor.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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 <SpecularReflections/SpecularReflectionsFeatureProcessor.h>
  9. #include <Atom/RHI/RHISystemInterface.h>
  10. #include <Atom/RPI.Public/RPISystemInterface.h>
  11. #include <Atom/RPI.Public/Pass/PassFilter.h>
  12. #include <RayTracing/RayTracingPass.h>
  13. #include <ReflectionScreenSpace/ReflectionScreenSpacePass.h>
  14. namespace AZ
  15. {
  16. namespace Render
  17. {
  18. void SpecularReflectionsFeatureProcessor::Reflect(ReflectContext* context)
  19. {
  20. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  21. {
  22. serializeContext
  23. ->Class<SpecularReflectionsFeatureProcessor, FeatureProcessor>()
  24. ->Version(1);
  25. }
  26. }
  27. void SpecularReflectionsFeatureProcessor::Activate()
  28. {
  29. EnableSceneNotification();
  30. }
  31. void SpecularReflectionsFeatureProcessor::Deactivate()
  32. {
  33. DisableSceneNotification();
  34. }
  35. void SpecularReflectionsFeatureProcessor::SetSSROptions(const SSROptions& ssrOptions)
  36. {
  37. m_ssrOptions = ssrOptions;
  38. UpdatePasses();
  39. }
  40. void SpecularReflectionsFeatureProcessor::OnRenderPipelineChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline,
  41. RPI::SceneNotification::RenderPipelineChangeType changeType)
  42. {
  43. if (changeType == RPI::SceneNotification::RenderPipelineChangeType::Added
  44. || changeType == RPI::SceneNotification::RenderPipelineChangeType::PassChanged)
  45. {
  46. UpdatePasses();
  47. }
  48. }
  49. void SpecularReflectionsFeatureProcessor::UpdatePasses()
  50. {
  51. RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
  52. RHI::Ptr<RHI::Device> device = rhiSystem->GetDevice();
  53. // disable raytracing if the platform does not support it
  54. m_ssrOptions.m_rayTracing &= device->GetFeatures().m_rayTracing;
  55. // determine size multiplier to pass to the shaders
  56. float sizeMultiplier = m_ssrOptions.m_halfResolution ? 0.5f : 1.0f;
  57. // parent SSR pass
  58. {
  59. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpacePass"), (AZ::RPI::Scene*) nullptr);
  60. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  61. {
  62. // enable/disable
  63. pass->SetEnabled(m_ssrOptions.m_enable);
  64. // reset frame delay if screenspace reflections are disabled
  65. if (!m_ssrOptions.m_enable)
  66. {
  67. ReflectionScreenSpacePass* reflectionScreenSpacePass = azrtti_cast<ReflectionScreenSpacePass*>(pass);
  68. reflectionScreenSpacePass->ResetFrameDelay();
  69. }
  70. // size multiplier
  71. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("RayTracingCoordsOutput"), AZ::Name("FallbackColor") };
  72. for (const auto& attachmentName : attachmentNames)
  73. {
  74. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  75. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpacePass", attachmentName.GetCStr());
  76. if (attachmentBinding)
  77. {
  78. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  79. if (attachment.get())
  80. {
  81. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  82. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  83. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  84. }
  85. }
  86. }
  87. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  88. });
  89. }
  90. // copy framebuffer pass
  91. {
  92. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionCopyFrameBufferPass"), (AZ::RPI::Scene*) nullptr);
  93. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  94. {
  95. // enable/disable
  96. pass->SetEnabled(m_ssrOptions.m_enable);
  97. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  98. });
  99. }
  100. // raytracing pass
  101. {
  102. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceRayTracingPass"), (AZ::RPI::Scene*) nullptr);
  103. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  104. {
  105. // enable/disable
  106. pass->SetEnabled(m_ssrOptions.m_rayTracing);
  107. if (m_ssrOptions.m_rayTracing)
  108. {
  109. // options
  110. RayTracingPass* rayTracingPass = azrtti_cast<RayTracingPass*>(pass);
  111. rayTracingPass->SetMaxRayLength(m_ssrOptions.m_maxRayDistance);
  112. Data::Instance<RPI::ShaderResourceGroup> rayTracingPassSrg = rayTracingPass->GetShaderResourceGroup();
  113. rayTracingPassSrg->SetConstant(m_invOutputScaleNameIndex, 1.0f / m_ssrOptions.GetOutputScale());
  114. rayTracingPassSrg->SetConstant(m_maxRoughnessNameIndex, m_ssrOptions.m_maxRoughness);
  115. rayTracingPassSrg->SetConstant(m_rayTraceFallbackDataNameIndex, m_ssrOptions.m_rayTraceFallbackData);
  116. rayTracingPassSrg->SetConstant(m_rayTraceFallbackSpecularNameIndex, m_ssrOptions.m_rayTraceFallbackSpecular);
  117. // size multiplier
  118. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("FallbackAlbedo"), AZ::Name("FallbackPosition"), AZ::Name("FallbackNormal") };
  119. for (const auto& attachmentName : attachmentNames)
  120. {
  121. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  122. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceRayTracingPass", attachmentName.GetCStr());
  123. if (attachmentBinding)
  124. {
  125. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  126. if (attachment.get())
  127. {
  128. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  129. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  130. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  131. }
  132. }
  133. }
  134. }
  135. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  136. });
  137. }
  138. // trace pass
  139. {
  140. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceTracePass"), (AZ::RPI::Scene*) nullptr);
  141. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  142. {
  143. // size multiplier
  144. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("ScreenSpaceReflectionOutput"), AZ::Name("TraceCoordsOutput") };
  145. for (const auto& attachmentName : attachmentNames)
  146. {
  147. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  148. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceTracePass", attachmentName.GetCStr());
  149. if (attachmentBinding)
  150. {
  151. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  152. if (attachment.get())
  153. {
  154. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  155. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  156. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  157. }
  158. }
  159. }
  160. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  161. });
  162. }
  163. // downsample depth linear pass
  164. {
  165. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceDownsampleDepthLinearPass"), (AZ::RPI::Scene*) nullptr);
  166. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  167. {
  168. // size multiplier
  169. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(AZ::Name("DownsampledDepthLinearInputOutput"));
  170. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [DownsampledDepthLinearInputOutput] on ReflectionScreenSpaceDownsampleDepthLinearPass");
  171. if (attachmentBinding)
  172. {
  173. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  174. if (attachment.get())
  175. {
  176. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  177. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  178. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  179. }
  180. }
  181. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  182. });
  183. }
  184. // filter pass
  185. {
  186. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceFilterPass"), (AZ::RPI::Scene*) nullptr);
  187. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  188. {
  189. // size multiplier
  190. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("Output") };
  191. for (const auto& attachmentName : attachmentNames)
  192. {
  193. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  194. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceFilterPass", attachmentName.GetCStr());
  195. if (attachmentBinding)
  196. {
  197. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  198. if (attachment.get())
  199. {
  200. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  201. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  202. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  203. }
  204. }
  205. }
  206. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  207. });
  208. }
  209. // copy history pass
  210. {
  211. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceCopyHistoryPass"), (AZ::RPI::Scene*) nullptr);
  212. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  213. {
  214. // enable/disable
  215. pass->SetEnabled(m_ssrOptions.m_temporalFiltering);
  216. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  217. });
  218. }
  219. }
  220. } // namespace Render
  221. } // namespace AZ