3
0

SpecularReflectionsFeatureProcessor.cpp 14 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. // disable raytracing if the platform does not support it
  52. if (RHI::RHISystemInterface::Get()->GetRayTracingSupport() == RHI::MultiDevice::NoDevices)
  53. {
  54. m_ssrOptions.m_reflectionMethod = SSROptions::ReflectionMethod::ScreenSpace;
  55. }
  56. // determine size multiplier to pass to the shaders
  57. float sizeMultiplier = m_ssrOptions.m_halfResolution ? 0.5f : 1.0f;
  58. // parent SSR pass
  59. {
  60. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpacePass"), (AZ::RPI::Scene*) nullptr);
  61. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  62. {
  63. // enable/disable
  64. pass->SetEnabled(m_ssrOptions.m_enable);
  65. // reset frame delay if screenspace reflections are disabled
  66. if (!m_ssrOptions.m_enable)
  67. {
  68. ReflectionScreenSpacePass* reflectionScreenSpacePass = azrtti_cast<ReflectionScreenSpacePass*>(pass);
  69. reflectionScreenSpacePass->ResetFrameDelay();
  70. }
  71. // size multiplier
  72. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("RayTracingCoordsOutput"), AZ::Name("FallbackColor") };
  73. for (const auto& attachmentName : attachmentNames)
  74. {
  75. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  76. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpacePass", attachmentName.GetCStr());
  77. if (attachmentBinding)
  78. {
  79. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  80. if (attachment.get())
  81. {
  82. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  83. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  84. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  85. }
  86. }
  87. }
  88. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  89. });
  90. }
  91. // copy framebuffer pass
  92. {
  93. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionCopyFrameBufferPass"), (AZ::RPI::Scene*) nullptr);
  94. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  95. {
  96. // enable/disable
  97. pass->SetEnabled(m_ssrOptions.m_enable);
  98. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  99. });
  100. }
  101. // raytracing pass
  102. {
  103. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceRayTracingPass"), (AZ::RPI::Scene*) nullptr);
  104. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  105. {
  106. // enable/disable
  107. pass->SetEnabled(m_ssrOptions.IsRayTracingEnabled());
  108. if (m_ssrOptions.IsRayTracingEnabled())
  109. {
  110. // options
  111. RayTracingPass* rayTracingPass = azrtti_cast<RayTracingPass*>(pass);
  112. rayTracingPass->SetMaxRayLength(m_ssrOptions.m_maxRayDistance);
  113. Data::Instance<RPI::ShaderResourceGroup> rayTracingPassSrg = rayTracingPass->GetShaderResourceGroup();
  114. rayTracingPassSrg->SetConstant(m_invOutputScaleNameIndex, 1.0f / m_ssrOptions.GetOutputScale());
  115. rayTracingPassSrg->SetConstant(m_maxRoughnessNameIndex, m_ssrOptions.m_maxRoughness);
  116. rayTracingPassSrg->SetConstant(m_reflectionMethodNameIndex, m_ssrOptions.m_reflectionMethod);
  117. rayTracingPassSrg->SetConstant(m_rayTraceFallbackSpecularNameIndex, m_ssrOptions.m_rayTraceFallbackSpecular);
  118. // size multiplier
  119. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("FallbackAlbedo"), AZ::Name("FallbackPosition"), AZ::Name("FallbackNormal") };
  120. for (const auto& attachmentName : attachmentNames)
  121. {
  122. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  123. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceRayTracingPass", attachmentName.GetCStr());
  124. if (attachmentBinding)
  125. {
  126. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  127. if (attachment.get())
  128. {
  129. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  130. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  131. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  132. }
  133. }
  134. }
  135. }
  136. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  137. });
  138. }
  139. // trace pass
  140. {
  141. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceTracePass"), (AZ::RPI::Scene*) nullptr);
  142. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  143. {
  144. // size multiplier
  145. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("ScreenSpaceReflectionOutput"), AZ::Name("TraceCoordsOutput") };
  146. for (const auto& attachmentName : attachmentNames)
  147. {
  148. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  149. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceTracePass", attachmentName.GetCStr());
  150. if (attachmentBinding)
  151. {
  152. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  153. if (attachment.get())
  154. {
  155. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  156. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  157. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  158. }
  159. }
  160. }
  161. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  162. });
  163. }
  164. // downsample depth linear pass
  165. {
  166. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceDownsampleDepthLinearPass"), (AZ::RPI::Scene*) nullptr);
  167. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  168. {
  169. // size multiplier
  170. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(AZ::Name("DownsampledDepthLinearInputOutput"));
  171. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [DownsampledDepthLinearInputOutput] on ReflectionScreenSpaceDownsampleDepthLinearPass");
  172. if (attachmentBinding)
  173. {
  174. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  175. if (attachment.get())
  176. {
  177. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  178. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  179. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  180. }
  181. }
  182. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  183. });
  184. }
  185. // filter pass
  186. {
  187. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceFilterPass"), (AZ::RPI::Scene*) nullptr);
  188. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  189. {
  190. // size multiplier
  191. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("Output") };
  192. for (const auto& attachmentName : attachmentNames)
  193. {
  194. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  195. AZ_Assert(attachmentBinding, "Failed to retrieve attachment binding [%s] on ReflectionScreenSpaceFilterPass", attachmentName.GetCStr());
  196. if (attachmentBinding)
  197. {
  198. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  199. if (attachment.get())
  200. {
  201. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  202. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  203. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  204. }
  205. }
  206. }
  207. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  208. });
  209. }
  210. // copy history pass
  211. {
  212. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceCopyHistoryPass"), (AZ::RPI::Scene*) nullptr);
  213. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  214. {
  215. // enable/disable
  216. pass->SetEnabled(m_ssrOptions.m_temporalFiltering);
  217. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  218. });
  219. }
  220. }
  221. } // namespace Render
  222. } // namespace AZ