SpecularReflectionsFeatureProcessor.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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/Feature/RayTracing/RayTracingPass.h>
  10. #include <Atom/RHI/RHISystemInterface.h>
  11. #include <Atom/RPI.Public/RPISystemInterface.h>
  12. #include <Atom/RPI.Public/Pass/PassFilter.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. 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.IsRayTracingEnabled());
  107. if (m_ssrOptions.IsRayTracingEnabled())
  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_reflectionMethodNameIndex, m_ssrOptions.m_reflectionMethod);
  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. if (attachmentBinding)
  123. {
  124. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  125. if (attachment.get())
  126. {
  127. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  128. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  129. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  130. }
  131. }
  132. }
  133. }
  134. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  135. });
  136. }
  137. // trace pass
  138. {
  139. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceTracePass"), (AZ::RPI::Scene*) nullptr);
  140. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  141. {
  142. // size multiplier
  143. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("ScreenSpaceReflectionOutput"), AZ::Name("TraceCoordsOutput") };
  144. for (const auto& attachmentName : attachmentNames)
  145. {
  146. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  147. if (attachmentBinding)
  148. {
  149. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  150. if (attachment.get())
  151. {
  152. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  153. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  154. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  155. }
  156. }
  157. }
  158. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  159. });
  160. }
  161. // downsample depth linear pass
  162. {
  163. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceDownsampleDepthLinearPass"), (AZ::RPI::Scene*) nullptr);
  164. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  165. {
  166. // size multiplier
  167. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(AZ::Name("DownsampledDepthLinearInputOutput"));
  168. if (attachmentBinding)
  169. {
  170. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  171. if (attachment.get())
  172. {
  173. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  174. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  175. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  176. }
  177. }
  178. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  179. });
  180. }
  181. // filter pass
  182. {
  183. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceFilterPass"), (AZ::RPI::Scene*) nullptr);
  184. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [sizeMultiplier](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  185. {
  186. // size multiplier
  187. static AZStd::vector<AZ::Name> attachmentNames = { AZ::Name("Output") };
  188. for (const auto& attachmentName : attachmentNames)
  189. {
  190. RPI::PassAttachmentBinding* attachmentBinding = pass->FindAttachmentBinding(attachmentName);
  191. if (attachmentBinding)
  192. {
  193. RPI::Ptr<RPI::PassAttachment> attachment = attachmentBinding->GetAttachment();
  194. if (attachment.get())
  195. {
  196. RPI::PassAttachmentSizeMultipliers& sizeMultipliers = attachment->m_sizeMultipliers;
  197. sizeMultipliers.m_widthMultiplier = sizeMultiplier;
  198. sizeMultipliers.m_heightMultiplier = sizeMultiplier;
  199. }
  200. }
  201. }
  202. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  203. });
  204. }
  205. // copy history pass
  206. {
  207. AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("ReflectionScreenSpaceCopyHistoryPass"), (AZ::RPI::Scene*) nullptr);
  208. AZ::RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
  209. {
  210. // enable/disable
  211. pass->SetEnabled(m_ssrOptions.m_temporalFiltering);
  212. return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  213. });
  214. }
  215. }
  216. } // namespace Render
  217. } // namespace AZ