Fix night sky: visible clouds, real moon-driven darkening

Three coordinated changes:
1. nightPaletteNew.cloud: void -> raised (slightly lighter than
   sky) so clouds have contrast against the new-moon sky
2. nightPaletteFull.cloudShadow: panel -> void so cloud undersides
   fade into the night sky, while the lit topsides (border) stand
   out clearly
3. getNightColor() now keeps 'light' (moonlight) bright and only
   partially darkens sky/bg. The previous version squashed
   everything toward black, killing cloud structure.

Shader side:
- max(0.15, uDayProgress) keeps a baseline moonlight tint on the
  lit side of clouds even when uDayProgress happens to be 0
- The final darken pass is now driven by nightFactor (sunAlt-based)
  instead of the unreliable uDayProgress
This commit is contained in:
Richard Zink committed 2026-10-07 19:25:50 +02:00
1 parent 58f1ecbc61
commit 673ed6cf0f
3 files changed
+48 -35

No files matched your search

+14 -12
View File
@@ -634,8 +634,8 @@ if (useVanta && typeof VANTA !== 'undefined') {
{ alt: 0.4, sky: hexToInt(ASH.steel), cloud: hexToInt(ASH.border), light: hexToInt(ASH.bone), bg: hexToInt(ASH.steel), cloudShadow: hexToInt(ASH.steel), sun: hexToInt(ASH.chalk), sunGlare: hexToInt(ASH.bone), sunLight: hexToInt(ASH.chalk), sunVis: 1 },
{ alt: Math.PI / 2, sky: hexToInt(ASH.steelLight), cloud: hexToInt(ASH.border), light: hexToInt(ASH.chalk), bg: hexToInt(ASH.steelLight), cloudShadow: hexToInt(ASH.steelLight), sun: hexToInt(ASH.chalk), sunGlare: hexToInt(ASH.bone), sunLight: hexToInt(ASH.chalk), sunVis: 1 }
];
window.nightPaletteNew = { sky: hexToInt(ASH.void), cloud: hexToInt(ASH.void), light: hexToInt(ASH.stone), bg: hexToInt(ASH.void), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.stone), sunGlare: hexToInt(ASH.ash), sunLight: hexToInt(ASH.stone) };
window.nightPaletteFull = { sky: hexToInt(ASH.panel), cloud: hexToInt(ASH.border), light: hexToInt(ASH.icon), bg: hexToInt(ASH.panel), cloudShadow: hexToInt(ASH.panel), sun: hexToInt(ASH.icon), sunGlare: hexToInt(ASH.mid), sunLight: hexToInt(ASH.icon) };
window.nightPaletteNew = { sky: hexToInt(ASH.void), cloud: hexToInt(ASH.raised), light: hexToInt(ASH.stone), bg: hexToInt(ASH.void), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.stone), sunGlare: hexToInt(ASH.ash), sunLight: hexToInt(ASH.stone) };
window.nightPaletteFull = { sky: hexToInt(ASH.panel), cloud: hexToInt(ASH.border), light: hexToInt(ASH.icon), bg: hexToInt(ASH.panel), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.icon), sunGlare: hexToInt(ASH.mid), sunLight: hexToInt(ASH.icon) };
window.weatherThemes = {
sunny: {
skyColor: hexToInt(ASH.steelLight),
@@ -687,8 +687,8 @@ window.sunPalettes = [
];
// Night palette based on moon phase (0 = new, 0.5 = full, 1 = new) - Ash colors
window.nightPaletteNew = { sky: hexToInt(ASH.void), cloud: hexToInt(ASH.void), light: hexToInt(ASH.stone), bg: hexToInt(ASH.void), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.stone), sunGlare: hexToInt(ASH.ash), sunLight: hexToInt(ASH.stone) };
window.nightPaletteFull = { sky: hexToInt(ASH.panel), cloud: hexToInt(ASH.border), light: hexToInt(ASH.icon), bg: hexToInt(ASH.panel), cloudShadow: hexToInt(ASH.panel), sun: hexToInt(ASH.icon), sunGlare: hexToInt(ASH.mid), sunLight: hexToInt(ASH.icon) };
window.nightPaletteNew = { sky: hexToInt(ASH.void), cloud: hexToInt(ASH.raised), light: hexToInt(ASH.stone), bg: hexToInt(ASH.void), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.stone), sunGlare: hexToInt(ASH.ash), sunLight: hexToInt(ASH.stone) };
window.nightPaletteFull = { sky: hexToInt(ASH.panel), cloud: hexToInt(ASH.border), light: hexToInt(ASH.icon), bg: hexToInt(ASH.panel), cloudShadow: hexToInt(ASH.void), sun: hexToInt(ASH.icon), sunGlare: hexToInt(ASH.mid), sunLight: hexToInt(ASH.icon) };
var MIN_NIGHT_BRIGHTNESS = 0.25; // minimum night brightness (even at new moon)
@@ -737,16 +737,18 @@ window.sunPalettes = [
sunGlare: lerpColor(window.nightPaletteNew.sunGlare, window.nightPaletteFull.sunGlare, s),
sunLight: lerpColor(window.nightPaletteNew.sunLight, window.nightPaletteFull.sunLight, s)
};
// Pull the whole night palette down by 'darkness' (a value
// 0..1 toward pure black) so new-moon skies are visibly darker
// than day, and full-moon skies still have some colour.
// 'light' is moonlight shining ON clouds / stars — keep it
// bright. Only sky / bg / bg-adjacent get the new-moon
// darkening, and only partially (otherwise new-moon nights
// are pitch black with no cloud structure).
var darkness = 1.0 - (MIN_NIGHT_BRIGHTNESS + (1 - MIN_NIGHT_BRIGHTNESS) * s);
var shift = -Math.round(255 * darkness * 0.4);
return {
sky: shiftColor(c.sky, -Math.round(255 * darkness * 0.6)),
cloud: shiftColor(c.cloud, -Math.round(255 * darkness * 0.6)),
light: shiftColor(c.light, -Math.round(255 * darkness * 0.6)),
bg: shiftColor(c.bg, -Math.round(255 * darkness * 0.6)),
cloudShadow: c.cloudShadow,
sky: shiftColor(c.sky, shift),
cloud: c.cloud, // keep contrast vs sky
light: c.light, // moonlight stays bright
bg: shiftColor(c.bg, shift),
cloudShadow: shiftColor(c.cloudShadow, Math.round(-shift * 0.5)),
sun: c.sun,
sunGlare: c.sunGlare,
sunLight: c.sunLight