Check out our latest project ✨ OpenChapter.io: free ebooks the way its meant to be 📖

WeatherSystem2D

An asset by Gregry
The page banner background of a mountain and forest
WeatherSystem2D hero image

Quick Information

0 ratings
WeatherSystem2D icon image
Gregry
WeatherSystem2D

A **reusable atmosphere kit for 2D Godot scenes** — a shader sky with a sun/moon and day-night cycle, drifting volumetric clouds, rain / snow / fog, reflective water that laps a beach or flows as a river, procedural terrain, and scattered vector props. Assemble a whole scene from code with one builder call — deterministically from a seed — and optionally make it *live*, with the sun tracking across the sky and weather fronts rolling in.

Supported Engine Version
4.3
Version String
4.7
License Version
MIT
Support Level
community
Modified Date
19 hours ago
Git URL
Issue URL

Godot 4 · Weather System 2D

A reusable atmosphere kit for 2D Godot scenes — a shader sky with a sun/moon and day-night cycle, drifting volumetric clouds, rain / snow / fog, reflective water that laps a beach or flows as a river, procedural terrain, and scattered vector props. Assemble a whole scene from code with one builder call — deterministically from a seed — and optionally make it live, with the sun tracking across the sky and weather fronts rolling in.

It began as a few-day project for a short anime-style scene and has grown into a well-documented, code-friendly kit for dropping atmosphere into other projects.

README Weather System 2D — rain, clouds, and reflective water

Status: functional and usable today (v0.1.0). Distributed as an installable addons/weather2d/ plugin — see the Roadmap for what's next.

Docs: Getting started · API reference · Architecture · Roadmap


Table of contents


Features

  • Build scenes from code — one WeatherScene builder call assembles sky + terrain + water + props into a ready node tree, deterministically from a seed.
  • Living atmosphere — opt-in .live() adds a SkyController: a day-night cycle (the sun/moon tracks, the sky palette shifts, stars come out), weather transitions (roll a storm in), and lightning — all frame-rate independent.
  • Unified sun model — one sun position + color drives the sky glow & disc, the lit side of the clouds, and the water glint together, so a scene reads as lit by one light.
  • Shader sky with a sun/moon disc, glow, and twinkling night stars.
  • Volumetric clouds with six style presets, sun-lit edges, wind drift, and cast shadows dappling the land & water.
  • Configurable water (WaterBody2D) — still / river / ocean-beach modes with foam, run-up, reflections, sun glint, and rain ripples; reacts to weather.
  • Procedural terrain (TerrainBand2D) — seeded mountains / hills / treeline silhouettes and a sand ground that shares a coastline with the water.
  • Rain / snow / fog overlays and wind that slants the rain and sways the foliage.
  • Vector prop scatter (PropScatter2D) — seeded, stratified trees / rocks / birds with depth haze, sway, and flight.
  • Painterly post-process — soft focus, grain, vignette.
  • Full-featured 2D map camera (MapCamera2D) with mouse / keyboard / gesture pan, zoom, and drag-with-inertia.
  • Scales down — a low_graphics() mode with cheap shader paths for weak or software (no-GPU) renderers.
  • Editor-live — the nodes are @tool scripts, so you preview changes right in the editor — plus a zero-dependency headless test suite.

Requirements

  • Godot 4.7 (developed and tested on 4.7, Forward+). No Parallax2D or other bleeding-edge nodes are required, so recent 4.x builds should work too.
  • No external dependencies or GDExtension — pure GDScript + shaders.

Quick start

  1. Clone the repo and open the folder as a Godot project (project.godot).
  2. Press Play — the main scene is the launcher: pick a scenario (Beach / Small Island / River / Lake / Mountains), then set the time of day (Dawn / Noon / Golden Hour / Dusk / Night), the weather (Clear / Cloudy / Foggy / Rainy / Stormy / Snowy), and the clouds (Wispy / Scattered / Cumulus / Overcast / Stormy, or Auto) — all independent axes, so you can do golden hour + storm clouds or dusk + cumulus. Drag rain / fog / wind, toggle snow / props / birds / painterly. Everything rebuilds live and reproducibly from a seed. It's the fastest way to see what the kit can do.

To use it in your own project, copy the addons/weather2d/ folder in and tick it on under Project → Project Settings → Plugins, then build a scene from code (below) or drop the nodes in by hand.

The WaterBody2D node (Phase 1)

The reworked water lives in the addon at addons/weather2d/. Open demos/water_demo.tscn to try it, or add a WaterBody2D node yourself — it owns its material, so it works with no setup:

var water := WaterBody2D.new()
water.mode = WaterBody2D.Mode.OCEAN_BEACH   # or STILL / RIVER
water.size = Vector2(1920, 540)
water.level = 0.55                          # waterline (0 top … 1 bottom)
water.foam_amount = 0.6
add_child(water)

Modes: Still (pond, ripples + reflections), River (surface streams along flow_direction, sits behind scenery), Ocean-Beach (an animated waterline laps up the shore with a foam band). Rolling sine waves (wave_height / wave_frequency) undulate the surface, and — when react_to_weather is on — rain from a SkyController (via the "SkySetting" group) darkens the water and kicks up more foam and bigger waves. Palette, waves, flow, foam, run-up and reflection are all inspector- and code-tweakable. To enable the addon in your own project, copy the addons/weather2d/ folder in and tick it on under Project → Project Settings → Plugins.

New: terrain bands (Phase 2)

TerrainBand2D renders one parallax band from a TerrainLayer resource — mountains / hills / treeline as seeded noise silhouettes with atmospheric haze, or a sand ground the water can wash over. Sand and water share an analytic coastline (coast_level + wave_*), so the ocean lines up with the land. See demos/beach_demo.tscn for mountains → hills → sand → ocean-beach water washing in.

var hills := TerrainBand2D.new()
hills.layer = TerrainLayer.hills()   # or .mountains() / .treeline() / .ground()
hills.size = Vector2(1920, 300)
add_child(hills)

New: build scenes from code (Phase 3)

The WeatherScene builder assembles a whole scene — sky gradient, parallax terrain bands, and water — into a ready node tree, deterministically from a seed. See demos/generated_demo.tscn (nothing is authored in that scene except one script).

var builder := WeatherScene.new()
builder.set_seed(20260705)
builder.time_of_day(TimeOfDay.golden_hour())     # Dawn / Noon / Golden Hour / Dusk / Night
builder.weather(WeatherPreset.stormy())          # Clear / Cloudy / Foggy / Rainy / Stormy / Snowy
builder.cloud_style(CloudPreset.cumulus())       # Wispy / Scattered / Cumulus / Overcast / Stormy
builder.terrain([
    TerrainLayer.mountains(),
    TerrainLayer.hills(),
    TerrainLayer.ground(),
])
builder.water(WaterBody2D.Mode.OCEAN_BEACH)
builder.props(true, 16)   # scatter SVG trees/rocks along the shore (seeded)
builder.painterly(true)   # soft-focus painterly post-process
add_child(builder.build())

Save a whole composition as a ScenePreset .tres and rebuild it anywhere with WeatherScene.new().from_preset(preset).build() — and go the other way with builder.to_preset() or ScenePreset.from_scene(root) to capture a code-built or hand-authored scene back into a preset. Or grab a ready-made recipe from Scenarios:

add_child(Scenarios.build("River", {"seed": 7, "time_of_day": TimeOfDay.dusk(), "weather": WeatherPreset.rainy()}).build())

Scenarios: Beach, Small Island, River, Lake, Mountains — the same ones the launcher exposes.

New: living scenes (Phase 5)

By default a built scene is a static composite. Call .live() and the builder adds a SkyController that animates the whole atmosphere at runtime — the sun tracks across the sky and the palette shifts through a day-night cycle, clouds drift with the wind and cast moving shadows, the water glints under the sun and ripples in the rain, and you can roll one weather front into another:

var scene := WeatherScene.new() \
    .time_of_day(TimeOfDay.golden_hour()) \
    .weather(WeatherPreset.clear()) \
    .terrain([TerrainLayer.mountains(), TerrainLayer.hills(), TerrainLayer.ground()]) \
    .water(WaterBody2D.Mode.OCEAN_BEACH) \
    .live(true, 0.01)   # animate; 0.01 = a slow day-night cycle (days per second)
    .lightning(true)    # storms flash
add_child(scene.build())

# Later, roll a storm in over 8 seconds:
var ctrl := scene.build().get_node("SkyController") as SkyController
ctrl.transition_to(WeatherPreset.stormy(), 8.0)

The controller joins the "SkySetting" group and emits updateRainAmount / updateCloudAmount, so a WaterBody2D (and any legacy subscriber) reacts to it exactly as it would to the classic SkySetting hub. All motion is scaled by frame delta, so it runs the same at any FPS. The launcher's Animate, Lightning, and Day–night speed controls drive this live.

The kit ships a hybrid art pipeline: PropScatter2D deterministically scatters vector props (trees, palms, bushes, rocks, flowers, driftwood, birds — the SVGs in assets/svg/) with even stratified placement, ground shadows, and animation (trees sway in the wind, birds fly across the sky — via foliage_wind / bird_fly shaders). The builder plants props per terrain layer, so back layers get small, hazy trees and near layers get big, crisp ones. PainterlyLayer adds a soft-focus + grain + vignette post-process. Weather adds .rain() / .snow() (rain.gdshader), .fog() (fog.gdshader), .clouds() (clouds.gdshader), and .wind() (sway + slant) — all reachable from the launcher.

Performance & low-graphics mode

The effects are full-screen fragment shaders, so on a weak or software (no-GPU) renderer they can get heavy — the clouds, the rain loop, and the painterly blur most of all. Two things help:

  • Faster by default: the fog / cloud-shadow / rain shaders skip their per-pixel noise entirely when the effect is off, and the clouds use a cheaper sun-rim probe — no meaningful change to the look.
  • Low-graphics mode: call .low_graphics() (or tick Low graphics in the launcher) and the kit takes cheap paths — fewer cloud octaves, no water screen-reflection or rain ripples, thinner rain, flat fog, and it skips the cloud-shadow and painterly passes and scatters fewer props. The composition is identical; the look is simplified.
WeatherScene.new().terrain([TerrainLayer.ground()]).water().low_graphics().build()

Tests

A zero-dependency headless suite lives in tests/ (113 checks, all passing on Godot 4.7 — the node logic, the builder, determinism, presets & round-trip, the Phase 5 sun model / day-night cycle / SkyController, the low-graphics wiring, weather-source robustness, and the rain→clouds coupling). Run it from the project root:

godot --headless --path . --script res://tests/run_tests.gd

It checks the node logic (property → shader wiring, mode enum, weather response, terrain factories/shader selection) and exits non-zero on failure. Visual/shader correctness is verified in the demo scenes — see tests/README.md.

How it works

A scene is assembled by the WeatherScene builder, not authored by hand. You describe the scene declaratively — time of day, weather, cloud style, terrain stack, water mode, props — and build() returns a ready Node2D tree (sky, clouds, terrain bands, water, overlays, camera), deterministic for a given seed.

For a living scene (.live()), the builder also adds a SkyController — the runtime hub. It holds the current TimeOfDay + WeatherPreset, advances the day-night cycle and any weather transition each frame (scaled by frame delta, so it's FPS-independent), and pushes the results into every material. It joins the "SkySetting" group and emits updateRainAmount / updateCloudAmount; effect nodes like WaterBody2D subscribe by looking the controller up in that group (get_tree().get_first_node_in_group("SkySetting")) and map the 0..1 value onto their own shader uniforms — so weather stays decoupled from the effects.

WeatherScene.build()  ─►  Node2D tree: Camera2D · Sky · Clouds · Terrain bands · Water ·
                          CloudShadow · Fog · Rain · (Painterly) · SkyController*   (*if .live())

SkyController  (group "SkySetting")
│  state:  TimeOfDay (sun, palette, stars) + WeatherPreset (rain / fog / cloud / wind)
│  step(delta):  day-night cycle · weather cross-fade · lightning
│  emits:  updateRainAmount, updateCloudAmount
│
├─ pushes uniforms ─► sky / clouds / cloud_shadow / fog / rain materials + water glint
└─ updateRainAmount ─► WaterBody2D  → darkens water, raises foam/waves, rain ripples

See docs/ARCHITECTURE.md for a full breakdown of the resources, nodes, builder, and value→uniform mappings.

Shaders

The reworked kit ships its canvas-item shaders in addons/weather2d/shaders/. These are the current, addon-canonical effects driven by the WeatherScene builder and the addon nodes:

Shader Purpose Key uniforms
sky Sky gradient with a sun/moon disc + glow and twinkling night stars, from the unified sun model sky_top/sky_bottom, sun_uv, sun_color, sun_size/sun_glow, star_intensity
water_body Mode-driven water (still / river / ocean-beach) — depth shading, sine-wave surface, foam band, run-up, screen reflections, sun glint & rain-ripple impacts mode, level, deep_color/shallow_color, wave_height/wave_frequency, flow_direction, foam_amount, swell_height, sun_uv/glint_strength, rain_ripple
clouds Layered fBm + ridged-detail volumetric clouds with lit tops / shadowed bases, a horizon perspective, sun-direction lighting and wind drift coverage, cloud_scale, density, softness, detail, cloud_dark/cloud_light, cloud_color, sun_uv/sun_tint, wind_dir
cloud_shadow Soft moving cloud shadows dappling the land & water, drifting with the wind coverage, wind_dir, shadow_color, strength, horizon
rain Falling rain / snow overlay (snow toggled by snow) with wind-driven slant amount, snow, slant
fog Distance-haze / fog wash over the scene density, fog_color
terrain_silhouette Seeded noise silhouettes (hills / mountains / treeline) with atmospheric haze roughness, seed, near_color/far_color
terrain_ground Sand / ground with grain and a dry→wet gradient, sharing the water's analytic coastline coast_level, wave_height/wave_frequency, grain/wetness params
foliage_wind Per-sprite wind sway for scattered trees/bushes (each out of phase) sway_strength, sway_speed
bird_fly Drift + bob + wing-flap animation for scattered birds flap/bob params
painterly Soft-focus blur + warmth + paper grain + vignette post-process blur, grain, vignette

Demos

Four scenes under demos/, each a good reference:

  • launcher.tscn (main scene) — the interactive playground: pick a scenario, time of day, weather and cloud style; drag rain / fog / wind; toggle snow / props / birds / painterly / animate — everything rebuilds live.
  • generated_demo.tscn — a whole scene built entirely from code in _ready() (nothing authored in the .tscn), running a slow day-night cycle with lightning.
  • beach_demo.tscn — mountains → hills → sand → ocean-beach water washing over the shore, showing the shared coastline.
  • water_demo.tscn — the three WaterBody2D modes side by side.

Roadmap

Everything through Phase 5 shipped in v0.1.0 — the addon, water, terrain, the code builder, and the living day-night simulation. The full history is in CHANGELOG.md; how it all fits together is in docs/ARCHITECTURE.md.

Shipped: an installable addon · WaterBody2D (still / river / ocean-beach with foam, reflections, sun glint, rain ripples) · procedural terrain + SVG prop scatter + painterly pass · the WeatherScene code builder with presets, scenarios & round-trip · living scenes (day-night cycle, weather transitions, cloud shadows, lightning) · a low_graphics() mode.

What's left is a short, mostly-optional backlog — media/GIFs for the public listing and optional visual polish (caustics, parallax clouds, wet-surface). See docs/ROADMAP.md.

Known limitations

  • Generated scenes are static unless you opt in — a plain WeatherScene.build() composites a fixed weather look (each material is set once). Call .live() to add a SkyController that animates the sky/weather/water and drives WaterBody2D.react_to_weather.
  • Clouds are a single layer — no parallax between high and low cloud decks yet (Phase 5 follow-up), and there are no god rays.
  • No caustics or live wet-sand edge — the sand's dry→wet blend is a static gradient rather than following the water's animated run-up (Phase 1 carry-overs).

Credits & license

The kit's shaders were written for this project, drawing on techniques shared by the excellent godotshaders.com community — in particular:

A **reusable atmosphere kit for 2D Godot scenes** — a shader sky with a sun/moon and day-night cycle, drifting volumetric clouds, rain / snow / fog, reflective water that laps a beach or flows as a river, procedural terrain, and scattered vector props. Assemble a whole scene from code with one builder call — deterministically from a seed — and optionally make it *live*, with the sun tracking across the sky and weather fronts rolling in.

Reviews

0 ratings

Your Rating

Headline must be at least 3 characters but not more than 50
Review must be at least 5 characters but not more than 500
Please sign in to add a review

Quick Information

0 ratings
WeatherSystem2D icon image
Gregry
WeatherSystem2D

A **reusable atmosphere kit for 2D Godot scenes** — a shader sky with a sun/moon and day-night cycle, drifting volumetric clouds, rain / snow / fog, reflective water that laps a beach or flows as a river, procedural terrain, and scattered vector props. Assemble a whole scene from code with one builder call — deterministically from a seed — and optionally make it *live*, with the sun tracking across the sky and weather fronts rolling in.

Supported Engine Version
4.3
Version String
4.7
License Version
MIT
Support Level
community
Modified Date
19 hours ago
Git URL
Issue URL

Open Source

Released under the AGPLv3 license

Plug and Play

Browse assets directly from Godot

Community Driven

Created by developers for developers