DiskLightDelegate.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 <Atom/RPI.Public/Scene.h>
  9. #include <AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h>
  10. #include <CoreLights/DiskLightDelegate.h>
  11. namespace AZ::Render
  12. {
  13. static const float DefaultConeAngleDegrees = 25.0f; // 25 degrees debug display
  14. DiskLightDelegate::DiskLightDelegate(LmbrCentral::DiskShapeComponentRequests* shapeBus, EntityId entityId, bool isVisible)
  15. : LightDelegateBase<DiskLightFeatureProcessorInterface>(entityId, isVisible)
  16. , m_shapeBus(shapeBus)
  17. {
  18. InitBase(entityId);
  19. }
  20. float DiskLightDelegate::CalculateAttenuationRadius(float lightThreshold) const
  21. {
  22. // Calculate the radius at which the irradiance will be equal to cutoffIntensity.
  23. const float intensity = GetPhotometricValue().GetCombinedIntensity(PhotometricUnit::Lumen);
  24. return Sqrt(intensity / lightThreshold);
  25. }
  26. void DiskLightDelegate::HandleShapeChanged()
  27. {
  28. if (GetLightHandle().IsValid())
  29. {
  30. GetFeatureProcessor()->SetDirection(GetLightHandle(), m_shapeBus->GetNormal());
  31. GetFeatureProcessor()->SetPosition(GetLightHandle(), GetTransform().GetTranslation());
  32. GetFeatureProcessor()->SetDiskRadius(GetLightHandle(), GetRadius());
  33. }
  34. }
  35. float DiskLightDelegate::GetSurfaceArea() const
  36. {
  37. const float radius = GetRadius();
  38. return Constants::Pi * radius * radius;
  39. }
  40. float DiskLightDelegate::GetRadius() const
  41. {
  42. return m_shapeBus->GetRadius() * GetTransform().GetUniformScale();
  43. }
  44. DiskLightDelegate::ConeVisualizationDimensions DiskLightDelegate::CalculateConeVisualizationDimensions(const float degrees) const
  45. {
  46. const float attenuationRadius = GetConfig()->m_attenuationRadius;
  47. const float shapeRadius = m_shapeBus->GetRadius();
  48. const float radians = DegToRad(degrees);
  49. const float coneRadius = Sin(radians) * attenuationRadius;
  50. const float coneHeight = Cos(radians) * attenuationRadius;
  51. return ConeVisualizationDimensions{ shapeRadius, shapeRadius + coneRadius, coneHeight };
  52. }
  53. Aabb DiskLightDelegate::GetLocalVisualizationBounds() const
  54. {
  55. const auto [radius, height] = [this]
  56. {
  57. if (GetConfig()->m_enableShutters)
  58. {
  59. const auto [innerTopRadius, innerBottomRadius, innerHeight] = CalculateConeVisualizationDimensions(
  60. GetMin(GetConfig()->m_outerShutterAngleDegrees, GetConfig()->m_innerShutterAngleDegrees));
  61. const auto [outerTopRadius, outerBottomRadius, outerHeight] =
  62. CalculateConeVisualizationDimensions(GetConfig()->m_outerShutterAngleDegrees);
  63. return AZStd::pair{ GetMax(outerBottomRadius, GetMax(innerBottomRadius, GetMax(innerTopRadius, outerTopRadius))),
  64. GetMax(innerHeight, outerHeight) };
  65. }
  66. const auto [topRadius, bottomRadius, height] = CalculateConeVisualizationDimensions(DefaultConeAngleDegrees);
  67. return AZStd::pair{ GetMax(topRadius, bottomRadius), height };
  68. }();
  69. return Aabb::CreateFromMinMax(Vector3(-radius, -radius, 0.0f), Vector3(radius, radius, height));
  70. }
  71. void DiskLightDelegate::DrawDebugDisplay(
  72. const Transform& transform,
  73. [[maybe_unused]] const Color& color,
  74. AzFramework::DebugDisplayRequests& debugDisplay,
  75. bool isSelected) const
  76. {
  77. debugDisplay.PushMatrix(transform);
  78. auto DrawConicalFrustum =
  79. [&debugDisplay](
  80. uint32_t numRadiusLines, const Color& color, float brightness, float topRadius, float bottomRadius, float height)
  81. {
  82. const Color displayColor = Color(color.GetAsVector3() * brightness);
  83. debugDisplay.SetColor(displayColor);
  84. debugDisplay.DrawWireDisk(Vector3(0.0f, 0.0f, height), Vector3::CreateAxisZ(), bottomRadius);
  85. for (uint32_t i = 0; i < numRadiusLines; ++i)
  86. {
  87. const float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi;
  88. const float cosAngle = Cos(radiusLineAngle);
  89. const float sinAngle = Sin(radiusLineAngle);
  90. debugDisplay.DrawLine(
  91. Vector3(cosAngle * topRadius, sinAngle * topRadius, 0.0f),
  92. Vector3(cosAngle * bottomRadius, sinAngle * bottomRadius, height));
  93. }
  94. };
  95. const uint32_t innerConeLines = 8;
  96. const Color coneColor = isSelected ? Color::CreateOne() : Color(0.0f, 0.75f, 0.75f, 1.0f);
  97. // With shutters enabled, draw inner and outer debug display frustums
  98. if (GetConfig()->m_enableShutters)
  99. {
  100. const auto [innerTopRadius, innerBottomRadius, innerHeight] = CalculateConeVisualizationDimensions(
  101. GetMin(GetConfig()->m_outerShutterAngleDegrees, GetConfig()->m_innerShutterAngleDegrees));
  102. const auto [outerTopRadius, outerBottomRadius, outerHeight] =
  103. CalculateConeVisualizationDimensions(GetConfig()->m_outerShutterAngleDegrees);
  104. // Outer cone frustum 'faded' debug cone
  105. const uint32_t outerConeLines = 9;
  106. // Draw a cone using the cone angle and attenuation radius
  107. DrawConicalFrustum(innerConeLines, coneColor, 1.0f, innerTopRadius, innerBottomRadius, innerHeight);
  108. DrawConicalFrustum(outerConeLines, coneColor, 0.75f, outerTopRadius, outerBottomRadius, outerHeight);
  109. }
  110. else
  111. {
  112. const auto [topRadius, bottomRadius, height] = CalculateConeVisualizationDimensions(DefaultConeAngleDegrees);
  113. DrawConicalFrustum(innerConeLines, coneColor, 1.0f, topRadius, bottomRadius, height);
  114. }
  115. debugDisplay.PopMatrix();
  116. }
  117. void DiskLightDelegate::SetEnableShutters(bool enabled)
  118. {
  119. Base::SetEnableShutters(enabled);
  120. if (GetLightHandle().IsValid())
  121. {
  122. GetFeatureProcessor()->SetConstrainToConeLight(GetLightHandle(), true);
  123. }
  124. }
  125. void DiskLightDelegate::SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees)
  126. {
  127. if (GetShuttersEnabled() && GetLightHandle().IsValid())
  128. {
  129. GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees));
  130. }
  131. }
  132. void DiskLightDelegate::SetEnableShadow(bool enabled)
  133. {
  134. Base::SetEnableShadow(enabled);
  135. if (GetLightHandle().IsValid())
  136. {
  137. GetFeatureProcessor()->SetShadowsEnabled(GetLightHandle(), enabled);
  138. }
  139. }
  140. void DiskLightDelegate::SetShadowBias(float bias)
  141. {
  142. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  143. {
  144. GetFeatureProcessor()->SetShadowBias(GetLightHandle(), bias);
  145. }
  146. }
  147. void DiskLightDelegate::SetNormalShadowBias(float bias)
  148. {
  149. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  150. {
  151. GetFeatureProcessor()->SetNormalShadowBias(GetLightHandle(), bias);
  152. }
  153. }
  154. void DiskLightDelegate::SetShadowmapMaxSize(ShadowmapSize size)
  155. {
  156. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  157. {
  158. GetFeatureProcessor()->SetShadowmapMaxResolution(GetLightHandle(), size);
  159. }
  160. }
  161. void DiskLightDelegate::SetShadowFilterMethod(ShadowFilterMethod method)
  162. {
  163. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  164. {
  165. GetFeatureProcessor()->SetShadowFilterMethod(GetLightHandle(), method);
  166. }
  167. }
  168. void DiskLightDelegate::SetFilteringSampleCount(uint32_t count)
  169. {
  170. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  171. {
  172. GetFeatureProcessor()->SetFilteringSampleCount(GetLightHandle(), static_cast<uint16_t>(count));
  173. }
  174. }
  175. void DiskLightDelegate::SetEsmExponent(float exponent)
  176. {
  177. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  178. {
  179. GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), exponent);
  180. }
  181. }
  182. void DiskLightDelegate::SetShadowCachingMode(AreaLightComponentConfig::ShadowCachingMode cachingMode)
  183. {
  184. if (GetShadowsEnabled() && GetLightHandle().IsValid())
  185. {
  186. GetFeatureProcessor()->SetUseCachedShadows(GetLightHandle(),
  187. cachingMode == AreaLightComponentConfig::ShadowCachingMode::UpdateOnChange);
  188. }
  189. }
  190. void DiskLightDelegate::SetAffectsGI(bool affectsGI)
  191. {
  192. if (GetLightHandle().IsValid())
  193. {
  194. GetFeatureProcessor()->SetAffectsGI(GetLightHandle(), affectsGI);
  195. }
  196. }
  197. void DiskLightDelegate::SetAffectsGIFactor(float affectsGIFactor)
  198. {
  199. if (GetLightHandle().IsValid())
  200. {
  201. GetFeatureProcessor()->SetAffectsGIFactor(GetLightHandle(), affectsGIFactor);
  202. }
  203. }
  204. } // namespace AZ::Render