133 lines
5.1 KiB
C#
133 lines
5.1 KiB
C#
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace DanieleMarotta.RiversongCodeShowcase
|
|
{
|
|
[RequiresWorldReadyForUpdate]
|
|
[GameSystemGroup(typeof(LateGameSystemGroup))]
|
|
[UpdateAfter(typeof(WorldTimeSystem))]
|
|
public class DayNightCycleLightingSystem : GameSystem, IInitializable, IDisposable, IUpdatable
|
|
{
|
|
[InjectService]
|
|
private GameConfig _config;
|
|
|
|
[InjectService]
|
|
private IScene _scene;
|
|
|
|
[InjectService]
|
|
private World _world;
|
|
|
|
private Quaternion _initialLightRotation;
|
|
|
|
public DayNightCycleLightingSystem(IServiceLocator serviceLocator) : base(serviceLocator)
|
|
{
|
|
}
|
|
|
|
public UniTask InitializeAsync()
|
|
{
|
|
_initialLightRotation = _scene.MainLight.transform.localRotation;
|
|
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Shader.SetGlobalFloat(ShaderProperties.NightBlend, 0);
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
var nightBlend = _world.TimeState.NightBlend;
|
|
Shader.SetGlobalFloat(ShaderProperties.NightBlend, nightBlend);
|
|
|
|
UpdateLightRig(nightBlend);
|
|
UpdateShadows(nightBlend);
|
|
UpdateAmbientLighting(nightBlend);
|
|
UpdatePostProcessing(nightBlend);
|
|
}
|
|
|
|
private void UpdateLightRig(float nightBlend)
|
|
{
|
|
_scene.LightRig.transform.localRotation = _world.TimeState.DayNightCycleStep switch
|
|
{
|
|
DayNightCycleStep.Day => Quaternion.identity,
|
|
DayNightCycleStep.DayToNight => Quaternion.Euler(0, nightBlend * 360, 0),
|
|
DayNightCycleStep.Night => Quaternion.identity,
|
|
DayNightCycleStep.NightToDay => Quaternion.Euler(0, -nightBlend * 360, 0),
|
|
_ => throw new ArgumentException()
|
|
};
|
|
|
|
var dayRotation = _initialLightRotation;
|
|
var nightRotation = _initialLightRotation * Quaternion.Euler(-90, 0, 0);
|
|
|
|
_scene.MainLight.transform.localRotation = _world.TimeState.DayNightCycleStep switch
|
|
{
|
|
DayNightCycleStep.Day => dayRotation,
|
|
DayNightCycleStep.DayToNight => Quaternion.Slerp(dayRotation, nightRotation, nightBlend),
|
|
DayNightCycleStep.Night => nightRotation,
|
|
DayNightCycleStep.NightToDay => Quaternion.Slerp(nightRotation, dayRotation, 1 - nightBlend),
|
|
_ => throw new ArgumentException()
|
|
};
|
|
|
|
_scene.NightLight.transform.localRotation = _world.TimeState.DayNightCycleStep switch
|
|
{
|
|
DayNightCycleStep.Day => nightRotation,
|
|
DayNightCycleStep.DayToNight => Quaternion.Slerp(nightRotation, dayRotation, nightBlend),
|
|
DayNightCycleStep.Night => dayRotation,
|
|
DayNightCycleStep.NightToDay => Quaternion.Slerp(dayRotation, nightRotation, 1 - nightBlend),
|
|
_ => throw new ArgumentException()
|
|
};
|
|
}
|
|
|
|
private void UpdateShadows(float nightBlend)
|
|
{
|
|
const float fadeSpeed = 2;
|
|
|
|
var mainLightT = Mathf.Clamp01(fadeSpeed * nightBlend);
|
|
UpdateShadows(_scene.MainLight, Mathf.Lerp(_config.Time.DayLighting.ShadowStrength, 0, mainLightT));
|
|
|
|
var nightLightT = Mathf.Clamp01(fadeSpeed * (1 - nightBlend));
|
|
UpdateShadows(_scene.NightLight, Mathf.Lerp(_config.Time.NightLighting.ShadowStrength, 0, nightLightT));
|
|
}
|
|
|
|
private static void UpdateShadows(Light light, float shadowStrength)
|
|
{
|
|
light.shadowStrength = shadowStrength;
|
|
light.shadows = shadowStrength > 0 ? LightShadows.Soft : LightShadows.None;
|
|
}
|
|
|
|
private void UpdateAmbientLighting(float nightBlend)
|
|
{
|
|
RenderSettings.ambientLight = Color.Lerp(_config.Time.DayLighting.AmbientColor, _config.Time.NightLighting.AmbientColor, nightBlend);
|
|
}
|
|
|
|
private void UpdatePostProcessing(float nightBlend)
|
|
{
|
|
_scene.NightVolume.weight = nightBlend;
|
|
_scene.BloomVolume.weight = nightBlend;
|
|
_scene.WarmTintVolume.weight = GetWarmTintBlend();
|
|
}
|
|
|
|
private float GetWarmTintBlend()
|
|
{
|
|
var step = _world.TimeState.DayNightCycleStep;
|
|
if (step != DayNightCycleStep.DayToNight && step != DayNightCycleStep.NightToDay) return 0;
|
|
|
|
var config = _config.Time;
|
|
|
|
var time = _world.TimeState.DayNightCycleTime;
|
|
var blend = step == DayNightCycleStep.DayToNight ? Mathf.Clamp01(time / config.DayToNightDuration) : Mathf.Clamp01(time / config.NightToDayDuration);
|
|
|
|
var rampUp = config.WarmTintRampUp;
|
|
var rampDown = config.WarmTintRampDown;
|
|
|
|
if (blend <= rampUp.x) return 0;
|
|
if (blend < rampUp.y) return Mathf.SmoothStep(0, 1, Mathf.InverseLerp(rampUp.x, rampUp.y, blend));
|
|
if (blend <= rampDown.x) return 1;
|
|
if (blend < rampDown.y) return Mathf.SmoothStep(1, 0, Mathf.InverseLerp(rampDown.x, rampDown.y, blend));
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
} |