DepthOfFieldSettings.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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 <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <AzFramework/Components/CameraBus.h>
  12. #include <AzFramework/Asset/AssetSystemBus.h>
  13. #include <Atom/RPI.Public/Image/ImageSystemInterface.h>
  14. #include <Atom/RPI.Public/Pass/PassFilter.h>
  15. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  16. #include <Atom/RPI.Public/RenderPipeline.h>
  17. #include <Atom/RPI.Public/RPIUtils.h>
  18. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  19. #include <Atom/RPI.Public/Scene.h>
  20. #include <Atom/RPI.Public/View.h>
  21. #include <PostProcess/DepthOfField/DepthOfFieldSettings.h>
  22. #include <PostProcess/PostProcessFeatureProcessor.h>
  23. #include <PostProcessing/DepthOfFieldCompositePass.h>
  24. #include <PostProcessing/DepthOfFieldBokehBlurPass.h>
  25. #include <PostProcessing/DepthOfFieldMaskPass.h>
  26. #include <PostProcessing/DepthOfFieldPencilMap.h>
  27. #include <PostProcessing/DepthOfFieldReadBackFocusDepthPass.h>
  28. namespace AZ
  29. {
  30. namespace Render
  31. {
  32. namespace DepthOfField
  33. {
  34. // Parameters for each quality are listed here.
  35. struct Quality
  36. {
  37. uint32_t sampleRadialDivision2 = 0;
  38. uint32_t sampleRadialDivision4 = 0;
  39. uint32_t sampleRadialDivision8 = 0;
  40. };
  41. static constexpr Quality QualitySet[DepthOfField::QualityLevelMax] =
  42. {
  43. // It is the radial division count of blur kernel.
  44. {2, 3, 4},
  45. {4, 4, 4}
  46. };
  47. }
  48. DepthOfFieldSettings::DepthOfFieldSettings(PostProcessFeatureProcessor* featureProcessor)
  49. : PostProcessBase(featureProcessor)
  50. {
  51. LoadPencilMap();
  52. m_pencilMapIndex = GetSceneSrg()->FindShaderInputImageIndex(Name("m_dofPencilMap"));
  53. // Get default
  54. auto viewSrg = GetDefaultViewSrg();
  55. AZ_Assert(viewSrg, "DepthOfFieldSettings : Failed to get the default render pipeline's default viewSrg.");
  56. m_passListWithHashOfDivisionNumber.Insert(Name("FrontblurDivision2"), AZ::RHI::Handle<uint32_t>(2));
  57. m_passListWithHashOfDivisionNumber.Insert(Name("BackblurDivision2"), AZ::RHI::Handle<uint32_t>(2));
  58. m_passListWithHashOfDivisionNumber.Insert(Name("MaskDivision2"), AZ::RHI::Handle<uint32_t>(2));
  59. m_passListWithHashOfDivisionNumber.Insert(Name("FrontblurDivision4"), AZ::RHI::Handle<uint32_t>(4));
  60. m_passListWithHashOfDivisionNumber.Insert(Name("BackblurDivision4"), AZ::RHI::Handle<uint32_t>(4));
  61. m_passListWithHashOfDivisionNumber.Insert(Name("MaskDivision4"), AZ::RHI::Handle<uint32_t>(4));
  62. m_passListWithHashOfDivisionNumber.Insert(Name("FrontblurDivision8"), AZ::RHI::Handle<uint32_t>(8));
  63. m_passListWithHashOfDivisionNumber.Insert(Name("BackblurDivision8"), AZ::RHI::Handle<uint32_t>(8));
  64. m_passListWithHashOfDivisionNumber.Insert(Name("MaskDivision8"), AZ::RHI::Handle<uint32_t>(8));
  65. }
  66. void DepthOfFieldSettings::LoadPencilMap()
  67. {
  68. m_pencilMap = RPI::LoadStreamingTexture(PencilMap::TextureFilePath);
  69. if (!m_pencilMap)
  70. {
  71. AZ_Error("DepthOfFieldSettings", false, "Failed to find or create an image instance from image asset '%s'", PencilMap::TextureFilePath);
  72. }
  73. }
  74. void DepthOfFieldSettings::OnConfigChanged()
  75. {
  76. m_parentSettings->OnConfigChanged();
  77. }
  78. void DepthOfFieldSettings::ApplySettingsTo(DepthOfFieldSettings* target, float alpha) const
  79. {
  80. AZ_Assert(target != nullptr, "DepthOfFieldSettings::ApplySettingsTo called with nullptr as argument.");
  81. // Auto-gen code to blend individual params based on their override value onto target settings
  82. #define OVERRIDE_TARGET target
  83. #define OVERRIDE_ALPHA alpha
  84. #include <Atom/Feature/ParamMacros/StartOverrideBlend.inl>
  85. #include <Atom/Feature/PostProcess/DepthOfField/DepthOfFieldParams.inl>
  86. #include <Atom/Feature/ParamMacros/EndParams.inl>
  87. #undef OVERRIDE_TARGET
  88. #undef OVERRIDE_ALPHA
  89. }
  90. void DepthOfFieldSettings::Simulate(float deltaTime)
  91. {
  92. m_deltaTime = deltaTime;
  93. UpdatePencilMapTexture();
  94. if (m_cameraEntityId.IsValid() && m_enabled)
  95. {
  96. UpdateCameraParameters();
  97. UpdateAutoFocusDepth(m_enabled);
  98. UpdateBlendFactor();
  99. }
  100. }
  101. void DepthOfFieldSettings::SetValuesToViewSrg(AZ::Data::Instance<RPI::ShaderResourceGroup> viewSrg)
  102. {
  103. viewSrg->SetConstant(m_cameraParametersIndex, m_configurationToViewSRG.m_cameraParameters);
  104. viewSrg->SetConstant(m_pencilMapTexcoordToCocRadiusIndex, m_configurationToViewSRG.m_pencilMapTexcoordToCocRadius);
  105. viewSrg->SetConstant(m_pencilMapFocusPointTexcoordUIndex, m_configurationToViewSRG.m_pencilMapFocusPointTexcoordU);
  106. viewSrg->SetConstant(m_cocToScreenRatioIndex, m_configurationToViewSRG.m_cocToScreenRatio);
  107. }
  108. void DepthOfFieldSettings::UpdatePencilMapTexture() const
  109. {
  110. GetSceneSrg()->SetImage(m_pencilMapIndex, m_pencilMap);
  111. }
  112. void DepthOfFieldSettings::UpdateCameraParameters()
  113. {
  114. // get camera parameters
  115. float viewFovRadian = 0.0f;
  116. float viewWidth = 0.0f;
  117. float viewHeight = 0.0f;
  118. float viewNear = 0.0f;
  119. float viewFar = 0.0f;
  120. Camera::CameraRequestBus::EventResult(viewFovRadian, m_cameraEntityId, &Camera::CameraRequestBus::Events::GetFovRadians);
  121. Camera::CameraRequestBus::EventResult(viewWidth, m_cameraEntityId, &Camera::CameraRequestBus::Events::GetFrustumWidth);
  122. Camera::CameraRequestBus::EventResult(viewHeight, m_cameraEntityId, &Camera::CameraRequestBus::Events::GetFrustumHeight);
  123. Camera::CameraRequestBus::EventResult(viewNear, m_cameraEntityId, &Camera::CameraRequestBus::Events::GetNearClipDistance);
  124. Camera::CameraRequestBus::EventResult(viewFar, m_cameraEntityId, &Camera::CameraRequestBus::Events::GetFarClipDistance);
  125. if (m_viewFovRadian != viewFovRadian
  126. || m_viewWidth != viewWidth
  127. || m_viewHeight != viewHeight
  128. || m_viewNear != viewNear
  129. || m_viewFar != viewFar)
  130. {
  131. m_viewFovRadian = viewFovRadian;
  132. m_viewWidth = viewWidth;
  133. m_viewHeight = viewHeight;
  134. m_viewNear = viewNear;
  135. m_viewFar = viewFar;
  136. }
  137. }
  138. void DepthOfFieldSettings::UpdateBlendFactor()
  139. {
  140. float focusDistance = 0.0f;
  141. if (m_enableAutoFocus)
  142. {
  143. if (m_focusedEntityId.IsValid())
  144. {
  145. AZ::Vector3 focusPosition;
  146. AZ::TransformBus::EventResult(focusPosition, m_focusedEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
  147. AZ::Transform cameraTransform;
  148. AZ::TransformBus::EventResult(cameraTransform, m_cameraEntityId, &AZ::TransformBus::Events::GetWorldTM);
  149. AZ::Vector3 cameraPosition = cameraTransform.GetTranslation();
  150. AZ::Vector3 forward = cameraTransform.GetBasisY();
  151. focusDistance = forward.Dot(focusPosition - cameraPosition);
  152. focusDistance = GetClamp(focusDistance, m_viewNear, m_viewFar);
  153. }
  154. else
  155. {
  156. focusDistance = m_viewNear + m_normalizedFocusDistanceForAutoFocus * (m_viewFar - m_viewNear);
  157. focusDistance = GetClamp(focusDistance, m_viewNear, m_viewFar);
  158. }
  159. }
  160. else
  161. {
  162. focusDistance = GetClamp(m_focusDistance, m_viewNear, m_viewFar);
  163. }
  164. m_configurationToViewSRG.m_cameraParameters[0] = m_viewFar;
  165. m_configurationToViewSRG.m_cameraParameters[1] = m_viewNear;
  166. m_configurationToViewSRG.m_cameraParameters[2] = focusDistance;
  167. m_viewAspectRatio = m_viewWidth / m_viewHeight;
  168. float cameraSensorDiagonalLength = PencilMap::EIS_35mm_DiagonalLength;
  169. float imageSensorHeight = cameraSensorDiagonalLength / sqrt(m_viewAspectRatio * m_viewAspectRatio + 1);
  170. float verticalTanHalfFov = tanf(m_viewFovRadian * 0.5f);
  171. // focalLength : Focusing distance of lens
  172. float focalLength = focusDistance * imageSensorHeight / (verticalTanHalfFov * 2.0f * focusDistance + imageSensorHeight);
  173. float cocToRatio = (focalLength * (focalLength / m_fNumber)) / (focusDistance - focalLength);
  174. m_configurationToViewSRG.m_cocToScreenRatio = cocToRatio / imageSensorHeight;
  175. // Ratio of filter diameter to screen, vertical reference.
  176. constexpr float ScreenApertureDiameter = 0.005f;
  177. // The diameter ratio of the reduced buffer compared to the next larger buffer.
  178. constexpr float DiameterDivisionScaleRatio = 4.0f;
  179. float screenApertureDiameterDivision2 = ScreenApertureDiameter * DiameterDivisionScaleRatio;
  180. float screenApertureDiameterDivision4 = screenApertureDiameterDivision2 * DiameterDivisionScaleRatio;
  181. float screenApertureDiameterDivision8 = screenApertureDiameterDivision4 * DiameterDivisionScaleRatio;
  182. // coc0Ratio : speed of blur end. The smaller the value, blur ends faster and changes suddenly
  183. // coc1Ratio : speed of blur start. The higher the value, blur starts later and changes suddenly
  184. constexpr float Coc0RatioBack = 0.51f;
  185. constexpr float Coc1RatioBack = 0.61f;
  186. constexpr float Coc0RatioFront = 1.0f;
  187. constexpr float Coc1RatioFront = 1.0f;
  188. float scaledDiameter = ScreenApertureDiameter * 0.25f;
  189. // This is the conversion factor for calculating the blend ratio from DofFactor.
  190. // coc0 : Confusion circle diameter screen ratio
  191. // coc1 : Confusion circle diameter screen ratio of one lower blur level;
  192. float backCoc0_Division2 = screenApertureDiameterDivision2 * Coc0RatioBack + scaledDiameter;
  193. float backCoc0_Division4 = screenApertureDiameterDivision4 * Coc0RatioBack + scaledDiameter;
  194. float backCoc0_Division8 = screenApertureDiameterDivision8 * Coc0RatioBack + scaledDiameter;
  195. float backCoc1_Division2 = ScreenApertureDiameter * Coc1RatioBack + scaledDiameter;
  196. float backCoc1_Division4 = screenApertureDiameterDivision2 * Coc1RatioBack + scaledDiameter;
  197. float backCoc1_Division8 = screenApertureDiameterDivision4 * Coc1RatioBack + scaledDiameter;
  198. float frontCoc0_Division2 = screenApertureDiameterDivision2 * Coc0RatioFront + scaledDiameter;
  199. float frontCoc0_Division4 = screenApertureDiameterDivision4 * Coc0RatioFront + scaledDiameter;
  200. float frontCoc0_Division8 = screenApertureDiameterDivision8 * Coc0RatioFront + scaledDiameter;
  201. float frontCoc1_Division2 = ScreenApertureDiameter * Coc1RatioFront + scaledDiameter;
  202. float frontCoc1_Division4 = screenApertureDiameterDivision2 * Coc1RatioFront + scaledDiameter;
  203. float frontCoc1_Division8 = screenApertureDiameterDivision4 * Coc1RatioFront + scaledDiameter;
  204. m_configurationToViewSRG.m_backBlendFactorDivision2[0] = m_configurationToViewSRG.m_cocToScreenRatio / (backCoc0_Division2 - backCoc1_Division2);
  205. m_configurationToViewSRG.m_backBlendFactorDivision2[1] = -backCoc1_Division2 / (backCoc0_Division2 - backCoc1_Division2);
  206. m_configurationToViewSRG.m_frontBlendFactorDivision2[0] = -m_configurationToViewSRG.m_cocToScreenRatio / (frontCoc0_Division2 - frontCoc1_Division2);
  207. m_configurationToViewSRG.m_frontBlendFactorDivision2[1] = -frontCoc1_Division2 / (frontCoc0_Division2 - frontCoc1_Division2);
  208. m_configurationToViewSRG.m_backBlendFactorDivision4[0] = m_configurationToViewSRG.m_cocToScreenRatio / (backCoc0_Division4 - backCoc1_Division4);
  209. m_configurationToViewSRG.m_backBlendFactorDivision4[1] = -backCoc1_Division4 / (backCoc0_Division4 - backCoc1_Division4);
  210. m_configurationToViewSRG.m_frontBlendFactorDivision4[0] = -m_configurationToViewSRG.m_cocToScreenRatio / (frontCoc0_Division4 - frontCoc1_Division4);
  211. m_configurationToViewSRG.m_frontBlendFactorDivision4[1] = -frontCoc1_Division4 / (frontCoc0_Division4 - frontCoc1_Division4);
  212. m_configurationToViewSRG.m_backBlendFactorDivision8[0] = m_configurationToViewSRG.m_cocToScreenRatio / (backCoc0_Division8 - backCoc1_Division8);
  213. m_configurationToViewSRG.m_backBlendFactorDivision8[1] = -backCoc1_Division8 / (backCoc0_Division8 - backCoc1_Division8);
  214. m_configurationToViewSRG.m_frontBlendFactorDivision8[0] = -m_configurationToViewSRG.m_cocToScreenRatio / (frontCoc0_Division8 - frontCoc1_Division8);
  215. m_configurationToViewSRG.m_frontBlendFactorDivision8[1] = -frontCoc1_Division8 / (frontCoc0_Division8 - frontCoc1_Division8);
  216. // max: radius x 2.0
  217. // min: radius x 0.5
  218. // Determine the maximum and minimum radius values so that the blurs in the front and back buffers are connected smoothly.
  219. m_maxBokehRadiusDivision2 = screenApertureDiameterDivision2;
  220. m_minBokehRadiusDivision2 = screenApertureDiameterDivision2 * 0.25f;
  221. m_maxBokehRadiusDivision4 = screenApertureDiameterDivision4;
  222. m_minBokehRadiusDivision4 = screenApertureDiameterDivision4 * 0.25f;
  223. m_maxBokehRadiusDivision8 = screenApertureDiameterDivision8;
  224. m_minBokehRadiusDivision8 = screenApertureDiameterDivision8 * 0.25f;
  225. // The ratio of the texcoord U of the pencil map to circle of confusion radius.
  226. // experimentally adjusted value.
  227. constexpr float PencilMapTexcoordToCocRadiusScale = 5.0f;
  228. float pencilMapTexcoordToCocRadius =
  229. PencilMapTexcoordToCocRadiusScale * m_fNumber * sqrt(m_viewFovRadian * 2.0f)
  230. / (focalLength / (focusDistance - focalLength) + 1.0f);
  231. m_configurationToViewSRG.m_pencilMapTexcoordToCocRadius = pencilMapTexcoordToCocRadius;
  232. m_configurationToViewSRG.m_pencilMapFocusPointTexcoordU = PencilMap::PencilMapFocusPointTexcoordU;
  233. }
  234. // [GFX TODO][ATOM-3035]This function is temporary and will change with improvement to the draw list tag system
  235. void DepthOfFieldSettings::UpdateAutoFocusDepth(bool enabled)
  236. {
  237. const Name TemplateNameReadBackFocusDepth = Name("DepthOfFieldReadBackFocusDepthTemplate");
  238. // [GFX TODO][ATOM-4908] multiple camera should be distingushed.
  239. RPI::PassFilter passFilter = RPI::PassFilter::CreateWithTemplateName(TemplateNameReadBackFocusDepth, GetParentScene());
  240. RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [this, enabled](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
  241. {
  242. auto* dofPass = azrtti_cast<AZ::Render::DepthOfFieldReadBackFocusDepthPass*>(pass);
  243. if (enabled)
  244. {
  245. m_normalizedFocusDistanceForAutoFocus = dofPass->GetNormalizedFocusDistanceForAutoFocus();
  246. }
  247. return RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
  248. });
  249. }
  250. void DepthOfFieldSettings::SetCameraEntityId(EntityId cameraEntityId)
  251. {
  252. m_cameraEntityId = cameraEntityId;
  253. }
  254. void DepthOfFieldSettings::SetEnabled(bool enabled)
  255. {
  256. m_enabled = enabled && m_cameraEntityId.IsValid();
  257. }
  258. void DepthOfFieldSettings::SetQualityLevel(uint32_t qualityLevel)
  259. {
  260. // Clamp quality level to be less than the size of the QualitySet array
  261. m_qualityLevel = AZStd::max(qualityLevel, static_cast<uint32_t>(AZStd::size(DepthOfField::QualitySet) - 1));
  262. m_sampleRadialDivision2 = DepthOfField::QualitySet[m_qualityLevel].sampleRadialDivision2;
  263. m_sampleRadialDivision4 = DepthOfField::QualitySet[m_qualityLevel].sampleRadialDivision4;
  264. m_sampleRadialDivision8 = DepthOfField::QualitySet[m_qualityLevel].sampleRadialDivision8;
  265. }
  266. void DepthOfFieldSettings::SetApertureF(float apertureF)
  267. {
  268. m_apertureF = apertureF;
  269. UpdateFNumber();
  270. }
  271. void DepthOfFieldSettings::UpdateFNumber()
  272. {
  273. // convert from [0, 1] to [1/256 - 1/0.12]
  274. constexpr float Min = DepthOfField::ApertureFMin;
  275. constexpr float Max = DepthOfField::ApertureFMax;
  276. float apertureF = 1.0f / Max + (1.0f / Min - 1.0f / Max) * m_apertureF;
  277. // convert from [1/256 - 1/0.12] to [256 - 0.12]
  278. m_fNumber = 1.0f / apertureF;
  279. }
  280. void DepthOfFieldSettings::SetFNumber([[maybe_unused]] float fNumber)
  281. {
  282. // FNumber is inferred from ApertureF
  283. }
  284. void DepthOfFieldSettings::SetFocusDistance(float focusDistance)
  285. {
  286. m_focusDistance = focusDistance;
  287. }
  288. void DepthOfFieldSettings::SetEnableAutoFocus(bool enableAutoFocus)
  289. {
  290. m_enableAutoFocus = enableAutoFocus;
  291. }
  292. void DepthOfFieldSettings::SetFocusedEntityId(EntityId focusedEntityId)
  293. {
  294. m_focusedEntityId = focusedEntityId;
  295. }
  296. void DepthOfFieldSettings::SetAutoFocusScreenPosition(Vector2 screenPosition)
  297. {
  298. m_autoFocusScreenPosition = screenPosition;
  299. }
  300. void DepthOfFieldSettings::SetAutoFocusSensitivity(float sensitivity)
  301. {
  302. m_autoFocusSensitivity = sensitivity;
  303. }
  304. void DepthOfFieldSettings::SetAutoFocusSpeed(float speed)
  305. {
  306. m_autoFocusSpeed = speed;
  307. }
  308. void DepthOfFieldSettings::SetAutoFocusDelay(float delay)
  309. {
  310. m_autoFocusDelay = delay;
  311. }
  312. void DepthOfFieldSettings::SetEnableDebugColoring(bool enabled)
  313. {
  314. m_enableDebugColoring = enabled;
  315. }
  316. AZ::RHI::Handle<uint32_t> DepthOfFieldSettings::GetSplitSizeForPass(const Name& passName) const
  317. {
  318. return m_passListWithHashOfDivisionNumber.Find(passName);
  319. }
  320. } // namespace Render
  321. } // namespace AZ