This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AgrarianGameArchive/Source/AgrarianGame/AgrarianSkyLightingController.cpp
T
2026-05-16 01:32:48 -07:00

148 lines
4.9 KiB
C++

// Copyright Pacificao. All Rights Reserved.
#include "AgrarianSkyLightingController.h"
#include "AgrarianGameState.h"
#include "Components/DirectionalLightComponent.h"
#include "Components/ExponentialHeightFogComponent.h"
#include "Components/SceneComponent.h"
#include "Components/SkyLightComponent.h"
#include "Engine/World.h"
AAgrarianSkyLightingController::AAgrarianSkyLightingController()
{
PrimaryActorTick.bCanEverTick = true;
bReplicates = false;
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
RootComponent = SceneRoot;
SunLight = CreateDefaultSubobject<UDirectionalLightComponent>(TEXT("SunLight"));
SunLight->SetupAttachment(SceneRoot);
SunLight->SetIntensity(NoonSunIntensity);
SunLight->SetLightColor(FLinearColor(1.0f, 0.96f, 0.86f));
SunLight->SetMobility(EComponentMobility::Movable);
SkyLight = CreateDefaultSubobject<USkyLightComponent>(TEXT("SkyLight"));
SkyLight->SetupAttachment(SceneRoot);
SkyLight->SetIntensity(ClearSkyLightIntensity);
SkyLight->SetMobility(EComponentMobility::Movable);
HeightFog = CreateDefaultSubobject<UExponentialHeightFogComponent>(TEXT("HeightFog"));
HeightFog->SetupAttachment(SceneRoot);
HeightFog->SetFogDensity(ClearFogDensity);
HeightFog->SetMobility(EComponentMobility::Movable);
}
void AAgrarianSkyLightingController::BeginPlay()
{
Super::BeginPlay();
RefreshSkyLighting();
}
void AAgrarianSkyLightingController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
RefreshSkyLighting();
}
void AAgrarianSkyLightingController::RefreshSkyLighting()
{
const UWorld* World = GetWorld();
const AAgrarianGameState* GameState = World ? World->GetGameState<AAgrarianGameState>() : nullptr;
if (!GameState)
{
return;
}
const float SunriseHour = GameState->bHasActiveTileSolarData ? GameState->SunriseHourLocal : 6.0f;
const float SunsetHour = GameState->bHasActiveTileSolarData ? GameState->SunsetHourLocal : 20.0f;
CurrentSunAlpha = CalculateSunAlpha(GameState->WorldHours, SunriseHour, SunsetHour);
CurrentWeather = GameState->Weather;
CurrentCloudAlpha = CalculateWeatherCloudAlpha(
GameState->Weather,
GameState->ActiveWeatherInputs.CloudCoverPercent,
GameState->ActiveWeatherInputs.bHasProviderData);
const float WeatherLightMultiplier = FMath::Lerp(1.0f, 0.35f, CurrentCloudAlpha);
const float SunIntensity = FMath::Lerp(NightSunIntensity, NoonSunIntensity, CurrentSunAlpha) * WeatherLightMultiplier;
const float SkyIntensity = FMath::Lerp(NightSkyLightIntensity, ClearSkyLightIntensity, CurrentSunAlpha) * FMath::Lerp(1.0f, 0.55f, CurrentCloudAlpha);
const float FogDensity = FMath::Lerp(ClearFogDensity, StormFogDensity, CurrentCloudAlpha);
const float SunPitch = FMath::Lerp(-8.0f, -72.0f, CurrentSunAlpha);
if (SunLight)
{
SunLight->SetWorldRotation(FRotator(SunPitch, NorthYawDegrees, 0.0f));
SunLight->SetIntensity(SunIntensity);
SunLight->SetLightColor(CalculateSunColor(CurrentSunAlpha, CurrentCloudAlpha));
}
if (SkyLight)
{
SkyLight->SetIntensity(SkyIntensity);
}
if (HeightFog)
{
HeightFog->SetFogDensity(FogDensity);
}
}
float AAgrarianSkyLightingController::CalculateSunAlpha(float HourOfDay, float SunriseHour, float SunsetHour) const
{
const float NormalizedHour = FMath::Fmod(HourOfDay + 24.0f, 24.0f);
const float SafeSunrise = FMath::Fmod(SunriseHour + 24.0f, 24.0f);
const float SafeSunset = FMath::Fmod(SunsetHour + 24.0f, 24.0f);
const float DayLength = FMath::Max(0.1f, SafeSunset >= SafeSunrise ? SafeSunset - SafeSunrise : (24.0f - SafeSunrise) + SafeSunset);
float HoursSinceSunrise = NormalizedHour - SafeSunrise;
if (HoursSinceSunrise < 0.0f)
{
HoursSinceSunrise += 24.0f;
}
if (HoursSinceSunrise > DayLength)
{
return 0.0f;
}
const float DayProgress = FMath::Clamp(HoursSinceSunrise / DayLength, 0.0f, 1.0f);
return FMath::Clamp(FMath::Sin(PI * DayProgress), 0.0f, 1.0f);
}
float AAgrarianSkyLightingController::CalculateWeatherCloudAlpha(EAgrarianWeatherType Weather, float ProviderCloudCoverPercent, bool bHasProviderCloudCover) const
{
float WeatherAlpha = 0.0f;
switch (Weather)
{
case EAgrarianWeatherType::Rain:
WeatherAlpha = 0.65f;
break;
case EAgrarianWeatherType::ColdWind:
WeatherAlpha = 0.45f;
break;
case EAgrarianWeatherType::Storm:
WeatherAlpha = 1.0f;
break;
default:
WeatherAlpha = 0.0f;
break;
}
if (bHasProviderCloudCover)
{
WeatherAlpha = FMath::Max(WeatherAlpha, FMath::Clamp(ProviderCloudCoverPercent / 100.0f, 0.0f, 1.0f));
}
return WeatherAlpha;
}
FLinearColor AAgrarianSkyLightingController::CalculateSunColor(float SunAlpha, float CloudAlpha) const
{
const FLinearColor DawnColor(1.0f, 0.62f, 0.38f);
const FLinearColor NoonColor(1.0f, 0.96f, 0.86f);
const FLinearColor StormColor(0.52f, 0.58f, 0.66f);
const FLinearColor TimeColor = FLinearColor::LerpUsingHSV(DawnColor, NoonColor, FMath::Clamp(SunAlpha, 0.0f, 1.0f));
return FLinearColor::LerpUsingHSV(TimeColor, StormColor, FMath::Clamp(CloudAlpha, 0.0f, 1.0f));
}