3
0

NewDepthOfFieldPasses.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 <AzCore/Math/MathUtils.h>
  9. #include <PostProcess/PostProcessFeatureProcessor.h>
  10. #include <PostProcess/DepthOfField/DepthOfFieldSettings.h>
  11. #include <PostProcessing/NewDepthOfFieldPasses.h>
  12. #include <Atom/RPI.Public/RenderPipeline.h>
  13. #include <Atom/RPI.Public/Scene.h>
  14. #include <Atom/RPI.Public/View.h>
  15. namespace AZ
  16. {
  17. namespace Render
  18. {
  19. // Must match the struct in NewDepthOfFieldCommon.azsli
  20. struct NewDepthOfFieldConstants
  21. {
  22. static constexpr uint32_t numberOfLoops = 3;
  23. static constexpr float loopCounts[] = { 8.0f, 16.0f, 24.0f };
  24. AZStd::array<float[4], 60> m_samplePositions; // XY are sample positions (normalized so max lenght is 1)
  25. // Z is the length of XY (0 - 1)
  26. // W is unused
  27. };
  28. // --- Depth of Field Parent Pass ---
  29. RPI::Ptr<NewDepthOfFieldParentPass> NewDepthOfFieldParentPass::Create(const RPI::PassDescriptor& descriptor)
  30. {
  31. RPI::Ptr<NewDepthOfFieldParentPass> pass = aznew NewDepthOfFieldParentPass(descriptor);
  32. return AZStd::move(pass);
  33. }
  34. NewDepthOfFieldParentPass::NewDepthOfFieldParentPass(const RPI::PassDescriptor& descriptor)
  35. : RPI::ParentPass(descriptor)
  36. { }
  37. bool NewDepthOfFieldParentPass::IsEnabled() const
  38. {
  39. if (!ParentPass::IsEnabled())
  40. {
  41. return false;
  42. }
  43. RPI::Scene* scene = GetScene();
  44. if (!scene)
  45. {
  46. return false;
  47. }
  48. PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor<PostProcessFeatureProcessor>();
  49. AZ::RPI::ViewPtr view = GetRenderPipeline()->GetFirstView(GetPipelineViewTag());
  50. if (!fp)
  51. {
  52. return false;
  53. }
  54. PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
  55. if (!postProcessSettings)
  56. {
  57. return false;
  58. }
  59. DepthOfFieldSettings* dofSettings = postProcessSettings->GetDepthOfFieldSettings();
  60. return (dofSettings != nullptr) && dofSettings->GetEnabled();
  61. }
  62. void NewDepthOfFieldParentPass::FrameBeginInternal(FramePrepareParams params)
  63. {
  64. RPI::Scene* scene = GetScene();
  65. PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor<PostProcessFeatureProcessor>();
  66. AZ::RPI::ViewPtr view = GetRenderPipeline()->GetFirstView(GetPipelineViewTag());
  67. if (fp)
  68. {
  69. PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view);
  70. if (postProcessSettings)
  71. {
  72. DepthOfFieldSettings* dofSettings = postProcessSettings->GetDepthOfFieldSettings();
  73. if (dofSettings)
  74. {
  75. dofSettings->SetValuesToViewSrg(view->GetShaderResourceGroup());
  76. }
  77. }
  78. }
  79. ParentPass::FrameBeginInternal(params);
  80. }
  81. // --- Tile Reduce Pass ---
  82. RPI::Ptr<NewDepthOfFieldTileReducePass> NewDepthOfFieldTileReducePass::Create(const RPI::PassDescriptor& descriptor)
  83. {
  84. RPI::Ptr<NewDepthOfFieldTileReducePass> pass = aznew NewDepthOfFieldTileReducePass(descriptor);
  85. return AZStd::move(pass);
  86. }
  87. NewDepthOfFieldTileReducePass::NewDepthOfFieldTileReducePass(const RPI::PassDescriptor& descriptor)
  88. : RPI::ComputePass(descriptor)
  89. {
  90. // Though this is a fullscreen pass, the shader computes 16x16 tiles with groups of 8x8 threads,
  91. // each thread outputting to a single pixel in the tiled min/max texture
  92. m_isFullscreenPass = false;
  93. }
  94. void NewDepthOfFieldTileReducePass::FrameBeginInternal(FramePrepareParams params)
  95. {
  96. AZ_Assert(GetOutputCount() > 0, "NewDepthOfFieldTileReducePass: No output bindings!");
  97. RPI::PassAttachment* outputAttachment = GetOutputBinding(0).GetAttachment().get();
  98. AZ_Assert(outputAttachment != nullptr, "NewDepthOfFieldTileReducePass: Output binding has no attachment!");
  99. RHI::Size outputSize = outputAttachment->m_descriptor.m_image.m_size;
  100. // The algorithm outputs the min/max CoC values from a 16x16 region using 8x8 threads
  101. u32 targetThreadCountX = outputSize.m_width * 8;
  102. u32 targetThreadCountY = outputSize.m_height * 8;
  103. SetTargetThreadCounts(targetThreadCountX, targetThreadCountY, 1);
  104. RPI::ComputePass::FrameBeginInternal(params);
  105. }
  106. // --- Filter Pass ---
  107. RPI::Ptr<NewDepthOfFieldFilterPass> NewDepthOfFieldFilterPass::Create(const RPI::PassDescriptor& descriptor)
  108. {
  109. RPI::Ptr<NewDepthOfFieldFilterPass> pass = aznew NewDepthOfFieldFilterPass(descriptor);
  110. return AZStd::move(pass);
  111. }
  112. NewDepthOfFieldFilterPass::NewDepthOfFieldFilterPass(const RPI::PassDescriptor& descriptor)
  113. : RPI::FullscreenTrianglePass(descriptor)
  114. { }
  115. void NewDepthOfFieldFilterPass::FrameBeginInternal(FramePrepareParams params)
  116. {
  117. NewDepthOfFieldConstants dofConstants;
  118. uint32_t sampleIndex = 0;
  119. // Calculate all the offset positions
  120. for (uint32_t loop = 0; loop < NewDepthOfFieldConstants::numberOfLoops; ++loop)
  121. {
  122. float radius = (loop + 1.0f) / float(NewDepthOfFieldConstants::numberOfLoops);
  123. float loopCount = NewDepthOfFieldConstants::loopCounts[loop];
  124. float angleStep = Constants::TwoPi / loopCount;
  125. // Every other loop slightly rotate sample ring so they don't line up
  126. float angle = (loop & 1) ? (angleStep * 0.5f) : 0;
  127. for (float i = 0.0f; i < loopCount; ++i)
  128. {
  129. Vector2 pos = Vector2::CreateFromAngle(angle);
  130. pos = pos * radius;
  131. dofConstants.m_samplePositions[sampleIndex][0] = pos.GetX();
  132. dofConstants.m_samplePositions[sampleIndex][1] = pos.GetY();
  133. dofConstants.m_samplePositions[sampleIndex][2] = radius;
  134. dofConstants.m_samplePositions[sampleIndex][3] = 0.0f;
  135. ++sampleIndex;
  136. angle += angleStep;
  137. }
  138. }
  139. m_shaderResourceGroup->SetConstant(m_constantsIndex, dofConstants);
  140. RPI::FullscreenTrianglePass::FrameBeginInternal(params);
  141. }
  142. } // namespace Render
  143. } // namespace AZ