From 596ad18ce360aa0e5aad53685e9b7edf19474269 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 12 Aug 2024 18:32:33 +0200 Subject: [PATCH] Add smooth light brightness fade out at last 10% of `ViewDistance` (if used) --- Source/Engine/Level/Actors/DirectionalLight.cpp | 4 ++-- Source/Engine/Level/Actors/Light.h | 15 ++++++++++++++- Source/Engine/Level/Actors/PointLight.cpp | 4 ++-- Source/Engine/Level/Actors/SpotLight.cpp | 4 ++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Level/Actors/DirectionalLight.cpp b/Source/Engine/Level/Actors/DirectionalLight.cpp index 97f9c3b58..5e52b4e74 100644 --- a/Source/Engine/Level/Actors/DirectionalLight.cpp +++ b/Source/Engine/Level/Actors/DirectionalLight.cpp @@ -18,11 +18,11 @@ void DirectionalLight::Draw(RenderContext& renderContext) { float brightness = Brightness; AdjustBrightness(renderContext.View, brightness); - const Float3 position = GetPosition() - renderContext.View.Origin; + Float3 position; if (Brightness > ZeroTolerance && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::DirectionalLights) && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer) - && (ViewDistance < ZeroTolerance || Float3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance)) + && CheckViewDistance(renderContext.View.Position, renderContext.View.Origin, position, brightness)) { RenderDirectionalLightData data; data.Position = position; diff --git a/Source/Engine/Level/Actors/Light.h b/Source/Engine/Level/Actors/Light.h index 9c3d6ff73..3138d996f 100644 --- a/Source/Engine/Level/Actors/Light.h +++ b/Source/Engine/Level/Actors/Light.h @@ -29,7 +29,7 @@ public: float Brightness = 3.14f; /// - /// Controls light visibility range. The distance at which the light becomes completely faded. Use a value of 0 to always draw light. + /// Controls light visibility range. The distance at which the light becomes completely faded (blend happens on the last 10% of that range). Use a value of 0 to always draw light. /// API_FIELD(Attributes="EditorOrder(35), Limit(0, float.MaxValue, 10.0f), EditorDisplay(\"Light\")") float ViewDistance = 0.0f; @@ -56,6 +56,19 @@ protected: // Adjust the light brightness used during rendering (called by light types inside SetupLightData callback) void AdjustBrightness(const RenderView& view, float& brightness) const; + FORCE_INLINE bool CheckViewDistance(const Float3& viewPosition, const Float3& viewOrigin, Float3& position, float& brightness) const + { + position = _transform.Translation - viewOrigin; + if (ViewDistance > ZeroTolerance) + { + const float dst2 = Vector3::DistanceSquared(viewPosition, position); + const float dst = Math::Sqrt(dst2); + brightness *= Math::Remap(dst, 0.9f * ViewDistance, ViewDistance, 1.0f, 0.0f); + return dst < ViewDistance; + } + return true; + } + public: // [Actor] void OnEnable() override; diff --git a/Source/Engine/Level/Actors/PointLight.cpp b/Source/Engine/Level/Actors/PointLight.cpp index 3c85be612..fbe3fd9e6 100644 --- a/Source/Engine/Level/Actors/PointLight.cpp +++ b/Source/Engine/Level/Actors/PointLight.cpp @@ -82,13 +82,13 @@ void PointLight::Draw(RenderContext& renderContext) { float brightness = ComputeBrightness(); AdjustBrightness(renderContext.View, brightness); - const Float3 position = GetPosition() - renderContext.View.Origin; + Float3 position; const float radius = GetScaledRadius(); if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::PointLights) && EnumHasAnyFlags(renderContext.View.Pass, DrawPass::GBuffer) && brightness > ZeroTolerance && radius > ZeroTolerance - && (ViewDistance < ZeroTolerance || Vector3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance)) + && CheckViewDistance(renderContext.View.Position, renderContext.View.Origin, position, brightness)) { RenderPointLightData data; data.Position = position; diff --git a/Source/Engine/Level/Actors/SpotLight.cpp b/Source/Engine/Level/Actors/SpotLight.cpp index 38457c94e..9494c14fa 100644 --- a/Source/Engine/Level/Actors/SpotLight.cpp +++ b/Source/Engine/Level/Actors/SpotLight.cpp @@ -130,7 +130,7 @@ void SpotLight::Draw(RenderContext& renderContext) { float brightness = ComputeBrightness(); AdjustBrightness(renderContext.View, brightness); - const Float3 position = GetPosition() - renderContext.View.Origin; + Float3 position; const float radius = GetScaledRadius(); const float outerConeAngle = GetOuterConeAngle(); if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpotLights) @@ -138,7 +138,7 @@ void SpotLight::Draw(RenderContext& renderContext) && brightness > ZeroTolerance && radius > ZeroTolerance && outerConeAngle > ZeroTolerance - && (ViewDistance < ZeroTolerance || Vector3::DistanceSquared(renderContext.View.Position, position) < ViewDistance * ViewDistance)) + && CheckViewDistance(renderContext.View.Position, renderContext.View.Origin, position, brightness)) { RenderSpotLightData data; data.Position = position;