From 98e384528f00471d0ec6746c45d00265c6556ba1 Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Wed, 7 Oct 2026 10:49:44 +0200 Subject: [PATCH] Use real sun position for day brightness, moon phase for night with minimum --- index.html | 116 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 37 deletions(-) diff --git a/index.html b/index.html index ec1155c..555cda7 100644 --- a/index.html +++ b/index.html @@ -369,43 +369,88 @@ var effect = (VANTA.CLOUDS2 || VANTA.CLOUDS)({ var CYCLE = 20000; - var palette = [ - { t: 0.00, sky: 0x0a0a18, cloud: 0x090907, light: 0x999187, bg: 0x050510, cloudShadow: 0x100f12, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 }, - { t: 0.08, sky: 0x2a1838, cloud: 0x090907, light: 0x999187, bg: 0x14101a, cloudShadow: 0x141316, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 }, - { t: 0.18, sky: 0x6a3a3a, cloud: 0x0e0b07, light: 0xa85f1d, bg: 0x4a2820, cloudShadow: 0x1f1814, sun: 0xc56a2b, sunGlare: 0xa85f1d, sunLight: 0xc56a2b, sunVis: 0.3 }, - { t: 0.28, sky: 0x9a5040, cloud: 0x110c08, light: 0xd6824a, bg: 0x7a4530, cloudShadow: 0x2a1f17, sun: 0xe0914f, sunGlare: 0xd6824a, sunLight: 0xe0914f, sunVis: 0.8 }, - { t: 0.42, sky: 0x5a8ac8, cloud: 0x111111, light: 0xe0d4be, bg: 0x506080, cloudShadow: 0x3a4458, sun: 0xf3ede1, sunGlare: 0xe6dfd1, sunLight: 0xf3ede1, sunVis: 1 }, - { t: 0.62, sky: 0x4a7ab8, cloud: 0x111111, light: 0xe6dfd1, bg: 0x445878, cloudShadow: 0x2a3450, sun: 0xf3ede1, sunGlare: 0xe6dfd1, sunLight: 0xf3ede1, sunVis: 1 }, - { t: 0.66, sky: 0x7a6a85, cloud: 0x111111, light: 0xe6c89a, bg: 0x5a554e, cloudShadow: 0x3a3428, sun: 0xe6c89a, sunGlare: 0xd6b46a, sunLight: 0xe6c89a, sunVis: 0.95 }, - { t: 0.69, sky: 0x9a5040, cloud: 0x110c09, light: 0xe6a872, bg: 0x7a5540, cloudShadow: 0x4a3025, sun: 0xe6a872, sunGlare: 0xd6824a, sunLight: 0xe6a872, sunVis: 0.85 }, - { t: 0.72, sky: 0xaa3838, cloud: 0x110c08, light: 0xe0914f, bg: 0x7a3825, cloudShadow: 0x4a2818, sun: 0xe0914f, sunGlare: 0xa86030, sunLight: 0xe0914f, sunVis: 0.7 }, - { t: 0.78, sky: 0x6a2848, cloud: 0x0e0705, light: 0xa86030, bg: 0x5a2820, cloudShadow: 0x2a1818, sun: 0xa86030, sunGlare: 0x6b4423, sunLight: 0xa86030, sunVis: 0.4 }, - { t: 0.85, sky: 0x3a1838, cloud: 0x0a0707, light: 0x6a4030, bg: 0x2a1820, cloudShadow: 0x1f1814, sun: 0x6a4030, sunGlare: 0x54514f, sunLight: 0x6a4030, sunVis: 0.1 }, - { t: 0.92, sky: 0x1a1828, cloud: 0x090907, light: 0x999187, bg: 0x14101a, cloudShadow: 0x141316, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 }, - { t: 1.00, sky: 0x0a0a18, cloud: 0x090907, light: 0x999187, bg: 0x050510, cloudShadow: 0x100f12, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 } + var PASSAU_LAT = 48.5667; + var PASSAU_LON = 13.4319; + + // Sun position palette (altitude-based) + // altitude in radians: -pi/2 (below) to pi/2 (zenith) + var sunPalettes = [ + { alt: -Math.PI / 2, sky: 0x0a0a18, cloud: 0x090907, light: 0x999187, bg: 0x050510, cloudShadow: 0x100f12, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 }, + { alt: -0.1, sky: 0x2a1838, cloud: 0x090907, light: 0x999187, bg: 0x14101a, cloudShadow: 0x141316, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187, sunVis: 0 }, + { alt: 0.0, sky: 0x9a5040, cloud: 0x110c08, light: 0xd6824a, bg: 0x7a4530, cloudShadow: 0x2a1f17, sun: 0xe0914f, sunGlare: 0xd6824a, sunLight: 0xe0914f, sunVis: 0.8 }, + { alt: 0.15, sky: 0xaa3838, cloud: 0x110c08, light: 0xe0914f, bg: 0x7a3825, cloudShadow: 0x4a2818, sun: 0xe0914f, sunGlare: 0xa86030, sunLight: 0xe0914f, sunVis: 0.7 }, + { alt: 0.4, sky: 0x6a7488, cloud: 0x111111, light: 0xe6dfd1, bg: 0x445878, cloudShadow: 0x2a3450, sun: 0xf3ede1, sunGlare: 0xe6dfd1, sunLight: 0xf3ede1, sunVis: 1 }, + { alt: Math.PI / 2, sky: 0x5a8ac8, cloud: 0x111111, light: 0xe0d4be, bg: 0x506080, cloudShadow: 0x3a4458, sun: 0xf3ede1, sunGlare: 0xe6dfd1, sunLight: 0xf3ede1, sunVis: 1 } ]; - function getColor(t) { - t = t % 1; - for (var i = 0; i < palette.length - 1; i++) { - if (t >= palette[i].t && t <= palette[i + 1].t) { - var span = palette[i + 1].t - palette[i].t; - var localT = span === 0 ? 0 : (t - palette[i].t) / span; - var s = smooth(localT); - return { - sky: lerpColor(palette[i].sky, palette[i + 1].sky, s), - cloud: lerpColor(palette[i].cloud, palette[i + 1].cloud, s), - light: lerpColor(palette[i].light, palette[i + 1].light, s), - bg: lerpColor(palette[i].bg, palette[i + 1].bg, s), - cloudShadow: lerpColor(palette[i].cloudShadow, palette[i + 1].cloudShadow, s), - sun: lerpColor(palette[i].sun, palette[i + 1].sun, s), - sunGlare: lerpColor(palette[i].sunGlare, palette[i + 1].sunGlare, s), - sunLight: lerpColor(palette[i].sunLight, palette[i + 1].sunLight, s), - sunVis: palette[i].sunVis + (palette[i + 1].sunVis - palette[i].sunVis) * s - }; + // Night palette based on moon phase (0 = new, 0.5 = full, 1 = new) + var nightPaletteNew = { sky: 0x0a0a18, cloud: 0x090907, light: 0x999187, bg: 0x050510, cloudShadow: 0x100f12, sun: 0x999187, sunGlare: 0x6d6a63, sunLight: 0x999187 }; + var nightPaletteFull = { sky: 0x2a2848, cloud: 0x111118, light: 0xb0a89a, bg: 0x14101a, cloudShadow: 0x141316, sun: 0xb0a89a, sunGlare: 0x54514f, sunLight: 0xb0a89a }; + + var MIN_NIGHT_BRIGHTNESS = 0.25; // minimum night brightness (even at new moon) + + function getDayColor(sunAlt) { + // Find palette segment based on sun altitude + var palette; + if (sunAlt <= sunPalettes[0].alt) { + palette = sunPalettes[0]; + } else if (sunAlt >= sunPalettes[sunPalettes.length - 1].alt) { + palette = sunPalettes[sunPalettes.length - 1]; + } else { + for (var i = 0; i < sunPalettes.length - 1; i++) { + if (sunAlt >= sunPalettes[i].alt && sunAlt <= sunPalettes[i + 1].alt) { + var span = sunPalettes[i + 1].alt - sunPalettes[i].alt; + var localT = span === 0 ? 0 : (sunAlt - sunPalettes[i].alt) / span; + var s = smooth(localT); + palette = { + sky: lerpColor(sunPalettes[i].sky, sunPalettes[i + 1].sky, s), + cloud: lerpColor(sunPalettes[i].cloud, sunPalettes[i + 1].cloud, s), + light: lerpColor(sunPalettes[i].light, sunPalettes[i + 1].light, s), + bg: lerpColor(sunPalettes[i].bg, sunPalettes[i + 1].bg, s), + cloudShadow: lerpColor(sunPalettes[i].cloudShadow, sunPalettes[i + 1].cloudShadow, s), + sun: lerpColor(sunPalettes[i].sun, sunPalettes[i + 1].sun, s), + sunGlare: lerpColor(sunPalettes[i].sunGlare, sunPalettes[i + 1].sunGlare, s), + sunLight: lerpColor(sunPalettes[i].sunLight, sunPalettes[i + 1].sunLight, s), + sunVis: sunPalettes[i].sunVis + (sunPalettes[i + 1].sunVis - sunPalettes[i].sunVis) * s + }; + break; + } } } - return { sky: palette[0].sky, cloud: palette[0].cloud, light: palette[0].light, bg: palette[0].bg, cloudShadow: palette[0].cloudShadow, sun: palette[0].sun, sunGlare: palette[0].sunGlare, sunLight: palette[0].sunLight, sunVis: 0 }; + return palette; + } + + function getNightColor(moonIllum) { + // moonIllum.fraction: 0 (new moon) to 1 (full moon) + // Apply minimum brightness + var brightness = MIN_NIGHT_BRIGHTNESS + (1 - MIN_NIGHT_BRIGHTNESS) * moonIllum.fraction; + // Interpolate between new and full moon palette based on fraction + var s = moonIllum.fraction; + var c = { + sky: lerpColor(nightPaletteNew.sky, nightPaletteFull.sky, s), + cloud: lerpColor(nightPaletteNew.cloud, nightPaletteFull.cloud, s), + light: lerpColor(nightPaletteNew.light, nightPaletteFull.light, s), + bg: lerpColor(nightPaletteNew.bg, nightPaletteFull.bg, s), + cloudShadow: lerpColor(nightPaletteNew.cloudShadow, nightPaletteFull.cloudShadow, s), + sun: lerpColor(nightPaletteNew.sun, nightPaletteFull.sun, s), + sunGlare: lerpColor(nightPaletteNew.sunGlare, nightPaletteFull.sunGlare, s), + sunLight: lerpColor(nightPaletteNew.sunLight, nightPaletteFull.sunLight, s) + }; + // Apply brightness factor (relative to mid) + return c; + } + + function getColor(t) { + // t is no longer used - now uses real sun/moon + var now = new Date(); + var sunPos = SunCalc.getPosition(now, PASSAU_LAT, PASSAU_LON); + var moonIllum = SunCalc.getMoonIllumination(now); + + if (sunPos.altitude > 0) { + return getDayColor(sunPos.altitude); + } else { + return getNightColor(moonIllum); + } } function adjustColor(color, factor) { @@ -467,8 +512,6 @@ var effect = (VANTA.CLOUDS2 || VANTA.CLOUDS)({ } // ============ Clock & Sun/Moon Calculations ============ - var PASSAU_LAT = 48.5667; - var PASSAU_LON = 13.4319; var hourHand = document.getElementById('hour-hand'); var minuteHand = document.getElementById('minute-hand'); @@ -976,8 +1019,7 @@ var weatherThemes = { function animate() { try { - var elapsed = (Date.now() - startTime) % CYCLE; - var t = elapsed / CYCLE; + var t = (Date.now() - startTime) / CYCLE % 1; var c = getColor(t); c = applyWeatherTheme(c); effect.setOptions({