Richard Zink 979134102d Runtime tile fetching for ground texture (ESRI)
Replace static ground.jpg with a dynamic tile-based system that
fetches new tiles from ESRI World Imagery as the camera moves
through the world.

- GROUND_TILE_Z = 11 (~13 km per tile)
- GROUND_MOSAIC_SIZE = 9 (9x9 = 81 tiles, 2304x2304 canvas)
- GROUND_BUFFER_TILES = 2 (refetch when within 2 tiles of edge)
- Passau tile at zoom 11: x=1102, y=710

Shader:
- Two new uniforms: uGroundCenter (mosaic centre in world units),
  uGroundSize (mosaic side length = 9)
- gUv = (hitPoint - uGroundCenter) / uGroundSize + 0.5 so the
  mosaic centre stays at UV (0.5, 0.5) as the camera drifts

Runtime:
- maybeRefetchGround() called every 1.5s with current camera
  position; if camera is in the buffer zone, mosaic centre is
  shifted and missing tiles re-fetched in parallel
- Canvas re-uploaded to GPU after each rebuild

Camera can now roam indefinitely — every time we approach the
mosaic edge, a fresh 9x9 of tiles is fetched.
2026-10-07 20:48:25 +02:00
2026-10-07 15:00:38 +02:00
2026-10-07 15:00:38 +02:00

Animated Background

An animated desktop background that runs in a browser. Features:

  • Time-of-day simulation with realistic color gradients driven by the actual sun position (computed from latitude/longitude via SunCalc).
  • Night brightness coupled to the moon phase (new moon = minimum, full moon = maximum), with a configurable minimum so the night is never pitch-black.
  • Live weather widget (Open-Meteo) showing current conditions and a 4-day forecast (morning, evening, full) at every timestamp.
  • Configurable units (metric °C+km/h or imperial °F+mph).
  • Configurable language (with English as the base; translations for German, Italian, Spanish, French, and Russian).
  • Configurable color theme (Ash, Gruvbox, Nord) - drop a new *.css file in the same directory and add an entry to window.THEMES to add a new theme.
  • Customisable location: set CONFIG.location.lat/lon, or let the browser's geolocation API pick one up automatically (falls back to London).
  • Optional custom location label (CONFIG.location.label) that overrides the OpenStreetMap reverse-geocoding lookup.
  • Configurable digital clock format string using ISO-8601-ish tokens (YYYY, MM, DD, HH, mm, ss, DDD, DDDD, MMM, MMMM, a, A, sss, T, escape sequences \n \t \, and full weekday/month names via the i18n dict).
  • Configurable debug panel (toggle collapse/expand with theme, units, and language dropdowns that apply at runtime).

Run with Docker

docker compose up --build

Then open http://localhost:58881/.

Run locally

The app is a single HTML page. With any static file server:

python3 -m http.server 58881

Open http://localhost:58881/.

Configuration

Edit config.js and reload the page:

window.CONFIG = {
    debug: 0,                          // 0 = hide debug panel, 1 = show
    theme: 'ash',                      // 'ash' | 'gruvbox' | 'nord'
    units: 'metric',                   // 'metric' | 'imperial'
    language: 'de',                    // 'en' | 'de' | 'it' | 'es' | 'fr' | 'ru'
    timeFormat: 'DD. MMMM, YYYY \u2012 HH:mm:SS',
    location: {
        lat: 48.5667,                  // latitude,  -90 to +90, north positive
        lon: 13.4319,                  // longitude, -180 to +180, east positive
        label: ''                       // optional custom place name;
                                       // if set, skips reverse-geocoding
    }
};

Adding a new language

Edit i18n.js and add entries for each existing key under your new language code, e.g.:

window.TRANSLATIONS['Sunrise']['xx'] = 'MyTranslation';

Adding a new theme

Drop a new *.css file next to the others and add an entry to window.THEMES:

window.THEMES['mytheme'] = 'mytheme.css';

Time format tokens

YYYY   4-digit year          (2026)
MM     month 01-12          (10)
DD     day 01-31            (07)
HH     hour 00-23 (24h)     (14)
mm     minute 00-59        (35)   lowercase!
ss     second 00-59        (22)   lowercase!
sss    millisecond 000-999 (456)
a      am/pm (lowercase)   (pm)
A      AM/PM (uppercase)   (PM)
T      literal 'T'

MMM    month short name     (Oct, Okt, Ott, ...)
MMMM   month full name      (October, Oktober, ...)
DDD    weekday short name   (Mon, Mo, Lu, ...)
DDDD   weekday full name    (Monday, Montag, ...)

\n     newline
\t     tab
\\     literal backslash

Files

.
├── background.html         the page (formerly index.html)
├── config.js                user-facing configuration
├── i18n.js                  translation strings (en/de/it/es/fr/ru)
├── ash.css                  default color theme
├── gruvbox.css              alternative color theme
├── nord.css                 alternative color theme
├── noise.png                background noise texture for Vanta
├── vendor/                  vendored third-party JS (no network needed)
│   ├── three.min.js         MIT (three.js)
│   ├── suncalc.js           ISC (SunCalc by mourner)
│   ├── vanta.clouds.min.js  MIT (Vanta.js Clouds)
│   ├── vanta.clouds2.min.js MIT (Vanta.js Clouds2)
│   └── LICENSE              per-library license attributions
├── default.conf             nginx server config (port 58881)
├── Dockerfile               builds nginx:alpine image
└── docker-compose.yml          one-service Compose file

Licenses

S
Description
No description provided
Readme MIT
6.5 MiB
0 Stars 1 Watchers 0 Forks
Languages
HTML 62.7%
JavaScript 27.5%
Python 7%
CSS 2.6%
Dockerfile 0.2%