Sky / Weather Demo
App: apps/sky_weather_demo/
Demonstrates the Sky / Weather content pack (engine PLM-262): a pure-Wren time-of-day
driver that paints a full day/night cycle — sky colour, sun direction and colour, ambient
fill, and distance fog — with zero engine source changes. Where the
Toon pack proved the shader half of Plume3D’s
engine-vs-pack boundary, this proves the policy half: the engine is policy-free — it
exposes neutral atmosphere knobs (setSky,
setAmbient, setFog, a directional sun Light) and takes no opinion on how
a day should look. The pack supplies the opinion — the curve that drives those knobs over time.
Run from root
Section titled “Run from root”% ./plume3d sky_weather_demoA small scene (a ground plane and a receding row of cubes) is lit by the changing sky. The demo
steps sunrise → noon → sunset → night and screenshots each
(sky_sunrise.png / sky_noon.png / sky_sunset.png / sky_night.png).
What’s in the pack (all content — no engine change)
Section titled “What’s in the pack (all content — no engine change)”| File | Kind | What it is |
|---|---|---|
Scripts/TimeOfDay.wren | policy driver | The reusable pack class. TimeOfDay.new(scene, "shaders/sky"), then tod.apply(t) each frame with t in [0,1). Interpolates keyframe tables for sky / sun / ambient / fog and aims the sun along a dawn→noon→dusk arc. |
main.wren | example | A small scene lit by the changing sky; steps through four times of day. |
shaders/src/*.slang | reused | The stock scene (lit) + sky (gradient) shaders — unchanged from the engine’s A#6 sky demo. |
The TimeOfDay driver
Section titled “The TimeOfDay driver”The whole day/night curve lives in Scripts/TimeOfDay.wren. Construct it once against the scene
and the sky shader, then drive it each frame with a normalized time of day:
import "Scripts/TimeOfDay" for TimeOfDay
_tod = TimeOfDay.new(_scene, "shaders/sky") // adds its own directional sun Light to the scene// ...each frame:_tod.apply(t) // t in [0,1)t is normalized time of day:
t | Time |
|---|---|
0.00 | midnight |
0.28 | sunrise |
0.50 | noon |
0.72 | sunset |
~0.80 | dusk |
apply(t) linear-interpolates the driver’s keyframe tables (horizon / zenith / sun colour /
sun energy / ambient) at t and pushes the result into every engine knob, then aims the sun:
an elevation arc (near the horizon at dawn/dusk, overhead at noon) plus an east→west sweep. It is
idempotent, so main.wren re-applies the current time each frame to let the look settle before
each screenshot.
The engine knobs it drives (all shipped — Block RFX A#6)
Section titled “The engine knobs it drives (all shipped — Block RFX A#6)”apply(t) writes only into the engine’s neutral atmosphere API — nothing the pack touches is new
engine surface:
Graphics.setSky(shader, 0, [horizon.r, horizon.g, horizon.b, 0, zenith.r, zenith.g, zenith.b, 0])— the full-screen gradient sky (mode0:params[0..2]= horizon colour,params[4..6]= zenith colour). The engine also ships a cubemap sky (mode1+setEnvironmentMap) a pack can drive instead.Graphics.setAmbient(r, g, b)— raw-linear ambient fill.Graphics.setFog(r, g, b, density, start, end)— atmospheric distance fog, its colour matched to the horizon so the far scene dissolves into the sky.- A directional sun
Light(type = 1): the driver rotates its node to aim the sun and callssetColor/energyfor the sun’s colour and intensity across the day.
The policy-vs-engine split
Section titled “The policy-vs-engine split”This is the point of the pack. The engine ships the pass and the knobs; the pack ships the look and the time-of-day curve:
- Engine (policy-free). Draws the sky, applies ambient and fog, lights the scene from the sun — with no notion of “morning” or “storm”. Identical raw-linear knobs whatever the game.
- Pack (policy). The keyframe tables and the sun arc in
TimeOfDay.wren— the opinion that a sunrise is warm and low, noon is bright and blue, night is dark with the sun off.
Re-theme the whole sky by editing the driver’s keyframe tables — still with no engine change. This is the same policy-free DNA as the engine’s health-free combat and raw-illuminance lighting, extended to atmosphere.
Extending it — a weather state machine (still pack policy)
Section titled “Extending it — a weather state machine (still pack policy)”A weather state machine (clear / overcast / rain / storm) layers on top exactly the same way: more Wren policy over the same knobs — lerp the sky and fog toward grey for overcast, drop the sun energy, add a rain particle preset. Cloud layers are a pack shader (a sky-shader variant, or billboard clouds via the existing particle system). None of it needs an engine change; it is left for a game to author.
- Graphics — Sky, fog & ambient (A#6) —
setSky/setAmbient/setFog, the neutral knobs the driver writes into. - Light — the directional sun (
type = 1,setColor,energy); the driver aims it via its Node rotation. - The sky, fog & ambient guide and the Sky Demo — the same A#6 knobs shown directly (gradient then cubemap sky, ambient, distance fog).
Notes and limitations
Section titled “Notes and limitations”- Content pack, not an engine feature. The day/night cycle is entirely
TimeOfDay.wren— the engine gains nothing. Packaging, licensing, and production sky/cloud art for a shippable pack are owner/business decisions; this in-repo demo is the exercised, gate-covered reference. - v1 reuses the stock A#6 shaders. The demo uses the
sky_demosky/sceneshaders verbatim; on MoltenVK they log one pre-existing non-fatal SPIR-V→MSL pipeline-variant warning at startup (the same onesky_demologs) — the scene and sky render correctly regardless. - The sky here is the gradient mode. A textured skybox is available through the cubemap sky mode
(
setSky(..., 1, [])+setEnvironmentMap) — a pack can drive that instead with no engine change.