Log inGet started
·
procgraph · drop-in viewer
asset⌬ procgraphprocGraphprimary: init.luau·part ofpackage effectShowcase.package·originates fromworld 0fc7535e-6…

storm.procGraph

A thunderstorm around a lone tower: rain driven slantwise by the wind that splashes off the ground and the tower, lightning bolts striking on the schedule `schedule.module` beside it keeps, sparks and smoke where each strike lands, and sheets of rain sweeping through. It is simul…

byzero-proxy @ DESKTOP-DB3UJOJ·posted 11d ago
What it does

storm

A thunderstorm around a lone tower: rain driven slantwise by the wind that splashes off the ground and the tower, lightning bolts striking on the schedule schedule.module beside it keeps, sparks and smoke where each strike lands, and sheets of rain sweeping through. It is simulated on the GPU in one solver family.

-- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it.
local e = entity.spawn("storm", { position = { 0, 0, 0 } })
e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" })
OutputWhat it draws
rainThe falling rain, storm_streak shader
splashSplashes where rain lands, storm_streak shader
sheetsSheets of rain sweeping through, storm_sheet shader
bolt1 to bolt4The lightning bolts, lightning_bolt shader
sparksSparks where strikes land, storm_streak shader
smokeSmoke rising where strikes land, storm_puff shader

The timeline has no end and plays at 60 fps. In the Procgen Effects Showcase world's fx_storm scene, the StormDirector component on the same entity reads this clock and, on the same schedule, swings the sun to each bolt, blazes point lights at the strike, lights the cloud deck and the puddles, shakes the camera and plays the thunder.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

storm: a thunderstorm around a lone tower, everything it simulates on the GPU in one solver family: wind-driven rain that splashes off the ground and the tower, lightning bolts that strike on a schedule (`schedule.module` beside it), and sparks and smoke where strikes land, with sheets of rain sweeping through.

id(name: ?) → void

argtypedescription
name?

V(x: ?, y: ?, z: ?) → void

argtypedescription
x?
y?
z?

attr(name: ?, stride: ?) → void

argtypedescription
name?
stride?

mul(a: ?, b: ?) → void

argtypedescription
a?
b?

speedOf( ) → void

ramp(keys: ?, type: ?) → void

argtypedescription
keys?
type?

C(r: ?, gg: ?, b: ?) → void

argtypedescription
r?
gg?
b?

set(domain: ?, name: ?, value: ?) → void

argtypedescription
domain?
name?
value?

draw(points: ?, mat: ?) → void

argtypedescription
points?
mat?

material(shader: ?, props: ?, blend: ?) → void

argtypedescription
shader?
props?
blend?

streaks(points: ?, width: ?, lenPerSpeed: ?, color: ?) → void

Streak card: turned onto its velocity, `width` across, `len` metres long per m/s.

argtypedescription
points?
width?
lenPerSpeed?
color?

lane(k: ?) → void

argtypedescription
k?

boxCollider(name: ?, cx: ?, cy: ?, cz: ?, sx: ?, sy: ?, sz: ?, bounce: ?) → void

argtypedescription
name?
cx?
cy?
cz?
sx?
sy?
sz?
bounce?

windForce(name: ?, dir: ?, strength: ?, spatial: ?, freq: ?, seed: ?, timeExpr: ?) → void

field.wind gusts by reading the clock in its own code, which pins the graph to a CPU cook every present. The same gusting is built here from a static spatial noise and a time curve wired into a field input, so time reaches the device as a live value and the graph presents without cooking.

argtypedescription
name?
dir?
strength?
spatial?
freq?
seed?
timeExpr?

axis(k: ?, v: ?) → void

argtypedescription
k?
v?

rainSource(name: ?, cx: ?, cy: ?, cz: ?, radius: ?, count: ?, rate: ?, life: ?, seed: ?) → void

argtypedescription
name?
cx?
cy?
cz?
radius?
count?
rate?
life?
seed?

jitter(name: ?, geo: ?, amp: ?, seed: ?, ty: ?) → void

Displace a curve's points sideways, fading to nothing at the strike end so the bolt lands exactly where the schedule says (`ty` is the strike height; the bolt is free to wander 14 m above it).

argtypedescription
name?
geo?
amp?
seed?
ty?

rnd(ch: ?, k: ?) → void

argtypedescription
ch?
k?
⌬ Metadata
descriptionstorm: a thunderstorm around a lone tower, everything it simulates on the GPU in one solver family: wind-driven rain that splashes off the ground and the tower, lightning bolts that strike on a schedule (`schedule.module` beside it), and sparks and smoke where strikes land, with sheets of rain sweeping through.kindeffect

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

34+items
✦
shader · born here
❒asset
# storm_sheet Additive upright sheet of slanted rain streaks in patchy gust bands, turned to face the camera about the vertical (`zero_billboard_axis` with world Y). Dozens of them sweep across the scene on the wind, which makes the rain read as weather. On each sheet three layers of fine lines run along a wind-slanted fall direction; every line has its own length and phase and falls with time, so they read as individual drops. A value-noise gust pattern, drifting with time, makes the sheet thick in gusts and threadbare between them. The sheet fades in and out over its life and toward its edges. The streaks are a cool blue `(0.46, 0.56, 0.78)` lifted by `ambient + flash * flash_gain`, scaled by `density` and faded with distance by `exp(-distance * fog)`. The `storm` graph (`storm/storm.procGraph`) draws its `sheets` output with it (additive, `flash` from the storm schedule's flash expression, `flash_gain` 0.9, `ambient` 0.16, `fog` 0.005, and `density` animated as `0.55 + 0.25 * sin(t * 0.9) + 0.14 * sin(t * 2.3 + 1.7)`): up to 90 sheets 46 to 92 wide, born on a wide disc upwind and carried across on the gusts for 7.5 to 9.5 s each. The graph writes `data0` as (life, a random seed, 0, 0). In the Procgen Effects Showcase world, the `fx_storm` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `flash` | float | 0.0 | Current strike brightness (range 0 to 8). | | `flash_gain` | float | 1.0 | Multiplies `flash` (range 0 to 20). | | `ambient` | float | 0.3 | Base brightness of the streaks (range 0 to 8). | | `density` | float | 1.0 | Multiplies the streaks; the storm graph swells it with the gusts (range 0 to 8). | | `fog` | float | 0.004 | Distance fade density (range 0 to 0.1). | | `vertexBoundsDilation` | float | 46 | How far the vertex hook moves a vertex past the mesh, in world units: the culling bounds grow by it so a moved vertex stays inside them. | ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 to 1: the fade in and out. | | `data0.y` | Per-sheet seed: offsets the lines and the gust pattern. |
▲ 0↑ born
✦
shader · born here
❒asset
# lightning_bolt Additive unlit surface shader for lightning ribbons: a hot white core, a blue-violet halo, and crawling flicker along the channel. On the ribbon `uv.x` runs along the bolt and `uv.y` across it. Across the ribbon three falloffs stack: a tight white-hot core `(1.0, 0.97, 0.92)` at 17 times brightness, a mid glow between the core colour and blue `(0.42, 0.52, 1.0)`, and a wide blue halo, all softened to zero at the ribbon's edges. Hot spots crawl along the channel from a value noise over `uv.x`, the storm clock `gt` and the bolt's own `phase`. Everything is scaled by `flash`, the strike envelope (0 dark, 1 the return stroke), and by `gain`; while `flash` is below 0.003 the fragments are discarded. The `storm` graph (`storm/storm.procGraph`) draws one forked bolt per strike in the storm schedule with it, each as its own output and material (additive, culling off, depth writes off): `flash` is that strike's envelope expression, `gt` the graph time, `phase` the strike's index, and `gain` is 1.0. Each bolt is a jittered, smoothed, resampled line from the strike's top to its target, branched three generations deep by `curve.branch`, and drawn as two crossed ribbons 3.4 wide that thin with each generation. In the Procgen Effects Showcase world, the `fx_storm` scene plays the graph. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `flash` | float | 1.0 | Strike envelope, 0 dark to 1 the return stroke (range 0 to 4). | | `gt` | float | 0.0 | The storm clock in seconds; drives the crawl of the hot spots. | | `phase` | float | 0.0 | Per-bolt offset of the crawling hot spots. | | `gain` | float | 1.0 | Multiplies the output (range 0 to 10). |
▲ 0↑ born
✦
shader · born here
❒asset
# storm_puff Alpha-blended smoke puff on a camera-facing card (`zero_billboard`), with wispy domain-warped edges, a sooty body, blue-white flash lighting and an ember glow while it is young. A domain-warped four-octave value noise, drifting with time and offset by the seed, erodes a round body. The puff fades in over the first 10 percent of its life and out between 0.45 and 1. Its dense core reads as soot `(0.030, 0.034, 0.045)` and its thin edges pick up a slate sky `(0.13, 0.15, 0.20)`, scaled by `ambient`. The storm's flash adds blue-white `(0.62, 0.70, 1.0)` light times `flash * flash_gain`, and the heat lane adds an orange ember glow `(1.0, 0.36, 0.06)`. The alpha is the body times the fades, the lane's opacity scale and `density`. The `storm` graph (`storm/storm.procGraph`) draws its `smoke` output with it (transparent, `flash` from the storm schedule's flash expression, `flash_gain` 1.7, `ambient` 1.0, `density` 0.8): smoke rising from every strike, dragged downwind and billowing as it ages. The graph writes `data0` as (life, a random seed, a heat ramp that falls from 1 to 0 by 0.28 of the life, 0.85). In the Procgen Effects Showcase world, the `fx_storm` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `flash` | float | 0.0 | Current strike brightness (range 0 to 8). | | `flash_gain` | float | 1.0 | Multiplies `flash` (range 0 to 20). | | `ambient` | float | 1.0 | Multiplies the soot-and-sky shade (range 0 to 8). | | `density` | float | 0.9 | Multiplies the alpha (range 0 to 4). | | `vertexBoundsDilation` | float | 6.5 | How far the vertex hook moves a vertex past the mesh, in world units: the culling bounds grow by it so a moved vertex stays inside them. | ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 born to 1 dead. | | `data0.y` | Per-puff seed. | | `data0.z` | Heat, 0 to 1: the ember glow. | | `data0.w` | Opacity scale; below 0.003 the puff is discarded. |
▲ 0↑ born
✦
shader · born here
❒asset
# storm_streak Additive billboard streak for rain, splash droplets and sparks: a card that turns about its own Y axis toward the camera (`zero_billboard_streak`). Colour comes from the element's `data0.rgb`, which is HDR so sparks can run hotter than 1, and an element whose colour fades to black vanishes (below 0.002 in every channel it is discarded). Across the card the streak is rounded (`1 - across^2`), so a thin card shows a soft edge; along it a bright head gives way to a long soft tail. The storm's lightning lifts every card by `ambient + flash * flash_gain`, which makes falling rain flicker into view in every strike. Distance fades the streak by `exp(-distance * fog)`, the streak fades in between 1.5 and 9 units from the camera, and the result is scaled by `gain`. The `storm` graph (`storm/storm.procGraph`) builds three additive materials from it: | Use | `flash` | `flash_gain` | `ambient` | `fog` | `gain` | |---|---|---|---|---|---| | Rain | storm flash expression | 1.0 | 0.11 | 0.010 | 1.0 | | Splash droplets | storm flash expression | 1.6 | 0.7 | 0.0045 | 1.0 | | Sparks and the smaller sparks they throw | 0 | 0.0 | 1.0 | 0.003 | 1.0 | For each, the graph turns the particle onto its velocity, sets its length from its speed and writes `data0` as a colour times a fade that takes a slow particle to black: wind-driven rain in a cool blue at random brightness, splash droplets thrown up where rain lands, and strike sparks cooling from `(11, 9, 6)` to black. In the Procgen Effects Showcase world, the `fx_storm` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `flash` | float | 0.0 | Current strike brightness (range 0 to 8). | | `flash_gain` | float | 1.0 | Multiplies `flash` (range 0 to 20). | | `ambient` | float | 1.0 | Base brightness of the streak (range 0 to 8). | | `fog` | float | 0.006 | Distance fade density (range 0 to 0.1). | | `gain` | float | 1.0 | Multiplies the output (range 0 to 20). | | `vertexBoundsDilation` | float | 0.05 | How far the vertex hook moves a vertex past the mesh, in world units: the culling bounds grow by it so a moved vertex stays inside them. | ## Lanes | Lane | Carries | |---|---| | `data0.rgb` | HDR colour; black discards the element. |
▲ 0↑ born
▣
module · born here
❒asset
# schedule The storm's clock. Every strike is a pure function of the storm phase, so the storm graph (as expressions over its own time) and the director (as Luau over the generator's clock) agree exactly, and the whole storm loops every `PERIOD` seconds. Two assets require it: the `storm` graph beside it (`storm.procGraph`, which builds its flash, bolt and burst expressions from `STRIKES`, `flashExpr`, `envelopeExpr` and `windowOne`) and the `StormDirector` component of the Procgen Effects Showcase world (lights, materials and thunder from `phase`, `envelope`, `afterglow` and `STRIKES`). ## Exports ### Values - `M.PERIOD`: `13.6`, the loop length in seconds. - `M.OFFSET`: `5.006`, the phase the storm is in at graph time 0. A strike has just landed there, so a paused frame is a hero frame. - `M.STRIKES`: the four strikes, each `{ t, kind, target, top, variant, weight }`. `t` is the phase the strike lands at, `target` where it lands, `top` where the bolt starts, and `weight` its brightness weight. `kind` is `"ground"` (throws sparks and smoke where it hits) or `"tower"` (hits the finial). `target` and `top` are in the storm graph's own space, where the tower stands at the origin; in the world they stand where the entity playing the graph does. | `t` | `kind` | `target` | `top` | `variant` | `weight` | |-----|--------|----------|-------|-----------|----------| | 1.6 | ground | `{ 15, 0, -8 }` | `{ 3, 135, -2 }` | 1 | 1.0 | | 5.0 | tower | `{ 0.05, 48.6, 0.1 }` | `{ -7, 135, 5 }` | 2 | 1.2 | | 8.6 | ground | `{ -19, 0, 7 }` | `{ -30, 135, 12 }` | 3 | 1.0 | | 11.0 | tower | `{ 0.05, 48.6, 0.1 }` | `{ 9, 135, 6 }` | 4 | 1.3 | - `M.PULSES`: the return strokes of a strike, each `{ delay after the leader, strength, decay rate per second }`: `{ 0.00, 1.00, 30 }`, `{ 0.11, 0.80, 26 }`, `{ 0.24, 0.62, 20 }`, `{ 0.43, 0.36, 11 }`. ### Functions - `M.phase(t)`: the storm phase at graph time `t`, `(t + OFFSET) % PERIOD`. - `M.envelope(ph, s)`: how bright strike `s` is at phase `ph`: 0 before the strike, about 1 at the return stroke. It sums every pulse whose delay has passed, each decaying exponentially at its rate. - `M.afterglow(ph, s)`: the cloud glow that lingers after strike `s`, at phase `ph`: `0.55 * exp(-d * 1.7) * min(d * 20, 1)` for `d` seconds after the strike, 0 before it. - `M.envelopeExpr(s)`: the same envelope as `envelope`, written as an anim expression string over `t`. - `M.afterglowExpr(s)`: the same afterglow as `afterglow`, as an expression string over `t`. - `M.flashExpr()`: the scene-wide flash as an expression string: the sum of every strike's envelope times its weight, capped at 3. - `M.windowExpr(only, lag, rise, fall)`: a burst of activity `lag` seconds after each strike, as a bump expression in [0, 1]: it rises with `min(d * rise, 1)` and falls with `exp(-d * fall)`. `only` limits it to strikes of one kind (`"ground"` or `"tower"`); `nil` includes every strike. - `M.windowOne(s, lag, rise, fall)`: the same bump for strike `s` alone. ## Usage ```luau local S = require("~.storm.schedule") local generator = entity.find("storm").component("Generator") local ph = S.phase(generator:getTime()) local flash = 0 for _, strike in ipairs(S.STRIKES) do flash += S.envelope(ph, strike) * strike.weight end -- the same flash, as an anim expression for a procGraph local flashExpr = proc.anim.expr(S.flashExpr()) -- a burst 0.15 s after each ground strike local bursts = S.windowExpr("ground", 0.15, 12, 1.0) ```
▲ 0↑ born
❒
package · born here
❒asset
# effectShowcase The procedural effects of the Procgen Effects Showcase world. Each one is a `.procGraph` that plays through a `Generator`, and every shader, material and module a graph draws with sits beside it in this package, so the package carries everything its graphs need. Each graph's README says what it makes, how to place it and what each of its inputs changes. ## Contents | Folder | Graphs | What they make | |---|---|---| | `combat/` | `impact`, `muzzleFlash`, `tracer` | A round striking a hard surface, the bloom at a barrel as a weapon fires, and the glowing streak of a round in flight. They draw with `fxFlash`, `fxSmoke` and `fxSpark` in `combat/shaders/`. | | `blast/` | `wall_blast` | A charge blowing a breach through a stone block wall, on a 9.6 s loop. | | `storm/` | `storm`, `tower` | A thunderstorm around a lone tower: wind-driven rain, lightning striking on the schedule `schedule.module` keeps, and sparks and smoke where strikes land. `tower` is the stone keep it stands around. | | `rift/` | `arcane_rift` | A rift tearing open in the ground, its motes and rubble moved by the compute shaders in `rift/compute/`. | | `dragon/` | `dragon_breath` | A dragon's fire breath sweeping a courtyard: a flame jet, rolling smoke and drifting embers. | | `launch/` | `launch` | A heavy-lift rocket liftoff on one looping timeline, with the heat-haze material `rk_haze_mat`. | | `waterfall/` | `wf_env`, `wf_water`, `wf_spray`, `wf_foam`, `wf_mist` | A waterfall built in parts: the cliff, basin and boulders, the falling and still water, the droplets, the foam where the falls land, and the mist with its rainbow. Its water materials are in `waterfall/materials/`. | | `shaders/` | | `fx_noise`, the noise functions the waterfall and wall blast shaders include. | ## Playing one A graph plays on a `Generator` component bound to it: ```lua -- `graph` is the graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("impact", { position = { 0, 1, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load" }) ``` Set a graph's inputs with the Generator's `params`, e.g. `params = { size = 3 }`.
▲ 0↑ born
backing path · effectShowcase.package/storm/storm.procGraph

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.