Climate (Core) layers a continuous seasonal-plus-daily temperature and the current season over the Calendar, registered via context.UseClimate. A new Lighting module (Graphics) adds DayNight: a daylight factor and ambient color from the calendar's time of day, pushed into the renderer's new AmbientLight (multiplied into world-space sprites only, so the scene darkens at night while screen-space overlays stay readable) and exposed as a sampleable SampleAt for the simulation. Both deterministic and GPU-free, covered by tests; docs updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f39ee9e787
commit
a684c23cd9
@@ -0,0 +1,66 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using MrGameEng.Core;
|
||||
|
||||
namespace MrGameEng.Lighting;
|
||||
|
||||
/// <summary>Colors for the day/night ambient: the tint at deep night and at midday.</summary>
|
||||
public readonly record struct DayNightSettings
|
||||
{
|
||||
/// <summary>Ambient tint at midnight (a dim, cool night).</summary>
|
||||
public Color NightColor { get; init; }
|
||||
|
||||
/// <summary>Ambient tint at noon (white = no tint).</summary>
|
||||
public Color DayColor { get; init; }
|
||||
|
||||
/// <summary>Sensible defaults: a dim blue night, untinted day.</summary>
|
||||
public static DayNightSettings Default =>
|
||||
new() { NightColor = new Color(45, 55, 95), DayColor = Color.White };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Day/night ambient driven by <see cref="Calendar.DayProgress"/>: a daylight factor (0 at midnight,
|
||||
/// 1 at noon) and an ambient color lerped from night to day. <see cref="SampleAt"/> is the sampleable
|
||||
/// light interface read by both the renderer (scene darkening) and the simulation (plant light);
|
||||
/// it returns the global daylight today and will return locally-shadowed light once point lights and
|
||||
/// occlusion land. Pure read-side, GPU-free and deterministic.
|
||||
/// </summary>
|
||||
public sealed class DayNight
|
||||
{
|
||||
private readonly Calendar _calendar;
|
||||
private readonly DayNightSettings _settings;
|
||||
|
||||
/// <summary>Creates the cycle reading <paramref name="calendar"/> with the given <paramref name="settings"/>.</summary>
|
||||
public DayNight(Calendar calendar, DayNightSettings settings)
|
||||
{
|
||||
_calendar = calendar ?? throw new ArgumentNullException(nameof(calendar));
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>Daylight factor in <c>[0, 1]</c> — 0 at midnight, 1 at noon, 0 again at midnight.</summary>
|
||||
public float Daylight
|
||||
{
|
||||
get
|
||||
{
|
||||
var value = -MathF.Cos(MathF.Tau * _calendar.DayProgress);
|
||||
return value > 0f ? value : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Global light intensity in <c>[0, 1]</c>; same as <see cref="Daylight"/> today.</summary>
|
||||
public float Intensity => Daylight;
|
||||
|
||||
/// <summary>Light intensity at a world point in <c>[0, 1]</c>. Global today; local (with shadows) later.</summary>
|
||||
public float SampleAt(Vector2 world) => Daylight;
|
||||
|
||||
/// <summary>Ambient tint for the scene: night color at night, day color at noon, eased between.</summary>
|
||||
public Color Ambient
|
||||
{
|
||||
get
|
||||
{
|
||||
var t = Smoothstep(Daylight);
|
||||
return Color.Lerp(_settings.NightColor, _settings.DayColor, t);
|
||||
}
|
||||
}
|
||||
|
||||
private static float Smoothstep(float x) => x * x * (3f - 2f * x);
|
||||
}
|
||||
Reference in New Issue
Block a user