Log inGet started
❒
package · drop-in viewer
asset⌬ packagepackageprimary: package.yaml·part ofpackage procgen.package·originates fromworld 0fc7535e-6…

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 READ…

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

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

FolderGraphsWhat they make
combat/impact, muzzleFlash, tracerA 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_blastA charge blowing a breach through a stone block wall, on a 9.6 s loop.
storm/storm, towerA 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_riftA rift tearing open in the ground, its motes and rubble moved by the compute shaders in rift/compute/.
dragon/dragon_breathA dragon's fire breath sweeping a courtyard: a flame jet, rolling smoke and drifting embers.
launch/launchA 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_mistA 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:

-- `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 }.

Interface

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

This asset doesn't declare a schema or structured payload.
⌬ Metadata
descriptionProcedural effects played through a Generator: impacts, muzzle flashes, tracers, a wall blast, a thunderstorm, an arcane rift, a dragon's fire breath, a rocket launch and a waterfall, with every shader, material and module they draw with.

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 the 199 items nearest this part. It holds more than this page lists.

199+items
✦
shader · born here
❒asset
# blast_puff Soft, domain-warped-fBm sprite used for the blast's fire (mode 0, additive) and lit smoke and dust (mode 1, alpha). Each particle is a camera-facing card (`zero_billboard`) cut to a disc and turned by its seed. Two-octave `fx_noise` fBm warps the coordinates, a four-octave fBm and a finer two-octave fBm erode the disc from the rim, and the domain drifts with the particle's life so the edge curls as it ages. Per-particle colour, life, seed and glow arrive on `data0`/`data1`. The sprite is depth-faded against the scene (soft particles) over 1 unit wherever a surface lies behind it; over the sky it keeps its full opacity. - Mode 0 (fire) is brightest in the dense middle: the colour runs from 0.55 of the lane colour at the thin edge to 1.25 of it plus a warm `(0.5, 0.32, 0.12)` boost scaled by glow at the core. It returns the colour multiplied by its coverage, for additive blending. - Mode 1 (smoke and dust) lights a sphere normal bumped by the noise: wrapped sun light, half the ambient light, a rim catching the sun, self-shadowing from the noise, and an orange fire underlight `(1.0, 0.4, 0.09)` that grows with the square of glow on the underside and core. - A mode above 1.5 draws a debug ramp from blue to orange over world height 0 to 14. The `wall_blast` graph (`blast/wall_blast.procGraph`) builds two materials from it: `fire_mat` (mode 0, additive) for the fireball and the white flash cards, and `smoke_mat` (mode 1, transparent) for the smoke column and cap, the smoke trailing behind flying rock, the dust puffs where rock lands and the dust ring rolling along the ground. The graph sizes each card from the particle's size and life and writes `data1` as (life, a random value, a glow ramp over life, a constant erode bias). The shader includes `@builtin::shaderModules.billboard`, `fx_noise` and `zero::scene_depth`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `mode` | float | 0 | Look selector, range 0 to 1: below 0.5 fire, 0.5 to 1.5 smoke and dust. | | `vertexBoundsDilation` | float | 34 | 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` | Colour; HDR for fire. | | `data0.a` | Peak opacity. | | `data1.x` | Life, 0 at birth to 1 at death; drifts the noise domain. | | `data1.y` | Seed: turns the card and offsets the noise. | | `data1.z` | Glow 0 to 1: the fire core boost in mode 0 and the fire underlight in mode 1. | | `data1.w` | Erode bias, subtracted from the shape so a larger value thins the puff. |
▲ 0↑ born
✦
shader · born here
❒asset
# blast_shock Ground shockwave disc: refracting ring edge plus a hot leading glare, driven by lanes (life, radius, strength, seed). It draws on a flat disc lying on the ground. Near the disc's rim a thin band bends the scene behind it: the shader reads the scene colour through `zero_scene_color_refract`, pushed radially outward from the centre (with the vertical push scaled by 0.35 for the foreshortened ground), by 46 times the band's amount (its profile times the life fade times strength). The band has a steep outer front and a long soft trail toward the centre, and its width wobbles with a three-octave `fx_noise` fBm around the circle. A warm white glare `(1.0, 0.86, 0.66)` sits on the leading edge. The ring is held at a thickness in metres, so it thins relative to the disc as the front runs out, and the whole effect fades with the square of the remaining life. The `wall_blast` graph (`blast/wall_blast.procGraph`) draws two fronts with it through its `shock_mat` material (transparent blend): one at strength 1.0 that grows to a radius of 30, and a second at strength 0.55, starting 0.12 s later, that grows to 24. Each lives 1.5 s; the graph scales a unit plane to the front's diameter and writes `data0` as (life, radius, strength, random seed). The shader includes `fx_noise` and `zero::scene_color`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `unused` | float | 0 | The one entry properties.yaml lists (range 0 to 1). Every value the shader reads comes from the lanes below. | ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 to 1. | | `data0.y` | Radius of the front in metres; sets the ring's width relative to the disc. | | `data0.z` | Strength: scales the bend and the glare. | | `data0.w` | Seed for the ripple noise. |
▲ 0↑ born
✦
shader · born here
❒asset
# blast_spark Additive streak or dot for sparks and embers; velocity-aligned via `zero_billboard_streak`. The instance's +Y runs along its velocity and its Y scale is stretched by speed, so a fast spark draws as a streak and a slow ember as a dot. The fragment shapes a capsule with a bright core and a soft tail, and flickers it with `0.72 + 0.28 * sin(time * rate + seed * 91)`. It returns the HDR colour times coverage with the coverage as alpha. The `wall_blast` graph (`blast/wall_blast.procGraph`) uses it through `spark_mat` (additive) for the embers and sparks thrown from the blast. The graph turns each particle onto its velocity, stretches its Y scale from 1 to 9 times its size over speeds 0 to 32, colours it from an HDR ramp that cools from yellow-white to dull red over life, and writes `data1` as (life, a random seed, a flicker rate of 45, 0). The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `unused` | float | 0 | The one entry properties.yaml lists (range 0 to 1). Every value the shader reads comes from the lanes below. | | `vertexBoundsDilation` | float | 0.1 | 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. | | `data0.a` | Intensity, multiplied into the colour. | | `data1.x` | Life 0 to 1, as the header states and the graph writes it. | | `data1.y` | Seed: the flicker's phase. | | `data1.z` | Flicker rate, multiplied by time inside the flicker sine. | | `data1.w` | 0. |
▲ 0↑ born
✦
shader · born here
❒asset
# blast_stone Procedural weathered stone (surface/PBR) for the wall and everything it breaks into. Per-instance lanes: tint, seed, heat (emissive glow), soot. The pattern is computed from the mesh UV scaled by 5.5 and offset by the seed, so every block reads differently. A height field of `fx_noise` fBm plus inverted worley cells gives pitting, and its finite-difference slope bends the normal. The base is warm sandstone, mixed between `(0.27, 0.21, 0.16)` and `(0.42, 0.34, 0.26)` by the tint lane, with broad fBm shading, fine speckle, darker crack lines, a grimy course toward the low end of the UV, and near-black soot by the soot lane. Roughness is 0.93 (0.85 along cracks). A hot block glows orange `(2.6, 0.75, 0.12)` through a vein pattern, scaled by the square of heat. The `wall_blast` graph (`blast/wall_blast.procGraph`) uses it through `stone_mat` on unit boxes scaled to blocks, with shadows on: the wall blocks that stand, the blocks the blast takes (held in place until the detonation), and the flying rubble. Standing blocks carry heat 0 and soot 0; rubble carries a heat ramp from 0.6 at birth to 0 and a soot ramp from 0.1 to 0.85 over its life. The shader includes `fx_noise`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `unused` | float | 0 | The one entry properties.yaml lists (range 0 to 1). Every value the shader reads comes from the lanes below. | ## Lanes | Lane | Carries | |---|---| | `data0.x` | Per-block tint 0 to 1, between the darker and lighter sandstone. | | `data0.y` | Per-block seed: offsets the noise pattern. | | `data0.z` | Heat 0 to 1: orange emissive glow, scaled by heat squared. | | `data0.w` | Char and soot 0 to 1: blends the albedo toward near-black. |
▲ 0↑ born
·
procgraph · born here
❒asset
# wall_blast A charge blowing a breach through a stone block wall, on a 9.6 s loop. The wall stands whole, a fireball bursts from its face a second in, the blocks around the breach are thrown out as tumbling, glowing debris with a spray of sparks, a shock ring runs out across the ground, and dust and smoke roll out and settle. Over the first fifth of a second of the next loop the breach knits back in. Everything is a function of the graph clock modulo the loop, so it repeats with no solver ever restarting. The wall runs along x at z = 8 in the generator's own space, and its blocks and debris are drawn with the `blast_stone` shader, the fire, smoke and dust with `blast_puff`, the sparks with `blast_spark` and the shock ring with `blast_shock`. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wall_blast", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` | Output | What it draws | |---|---| | `stone` | The wall's blocks, the breach's blocks while they stand, and the debris | | `fire` | The fireball at the wall face | | `sparks` | Sparks thrown out with the debris | | `shock` | The shock ring on the ground | | `smoke` | Smoke rising from the breach | | `dust` | Dust rolling out across the ground | | `light` | The light of the blast | The timeline has no end and plays at 60 fps.
▲ 0↑ born
·
procgraph · born here
❒asset
# impact A round striking a hard surface: a flash, a spray of sparks thrown back off it that fall and cool, a burst of dust and grit that billows and settles, and a flicker of light on the surface. Fire it where the round lands, with the effect's -Z turned along the normal of the surface it struck, and let it go when it ends: ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local function hitEffect(position, normal) local e = entity.spawn("impact", { position = position, temporary = true }) e:lookAt({ position[1] + normal[1], position[2] + normal[2], position[3] + normal[3] }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "hold" }) e.component.get("Generator").events.onFinished:connect(function() e:despawn() end) return e end ``` | Input | Default | What it does | |---|---|---| | `size` | 1 | How big the strike is: 1 a rifle round on concrete, 3 a heavy round, 0.4 a pistol. | | `light` | 1 | Strength of the light it throws, as a multiple of the default. | Set them with the Generator's `params`, e.g. `params = { size = 3 }`. It plays 66 frames at 60 fps (1.1 s). Every play with the same params plays the frames the first one cooked.
▲ 0↑ born
·
procgraph · born here
❒asset
# muzzleFlash The bloom at a barrel the instant a weapon fires: a ragged star of light and a tongue of flame down the bore, gone within three frames; a spray of burning powder that streaks out, falls and cools; a few puffs of smoke that swell, rise and thin; and a light that throws the flash on whatever stands near. The bore runs along the effect's -Z. Stand it on a child of the weapon at the muzzle, so it follows the weapon, and play it from the start on each shot: ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local function mountFlash(weapon, muzzleOffset) local muzzle = entity.spawn("muzzle", { parent = weapon.id, position = muzzleOffset }) muzzle.component.add("Generator", { graph = graph, playOn = "manual", ending = "hold" }) local flash = muzzle.component.get("Generator") return function() flash:seek(0) flash:play() end end ``` | Input | Default | What it does | |---|---|---| | `size` | 0.28 | Width of the flash in metres: a pistol at 0.12, a rifle at 0.28, a tank gun at 1.2. Every layer scales with it. | | `light` | 1 | Strength of the light it throws, as a multiple of the default. | It plays 54 frames at 60 fps (0.9 s). Played again, it plays the frames its first play cooked, so a weapon firing on full auto cooks it once.
▲ 0↑ born
✦
shader · born here
❒asset
# fxFlash The bloom of a discharge, drawn procedurally on a card for additive blending. With `shape` 0 it is a ragged star facing the camera (`zero_billboard`): five to seven spikes of hashed length and turn around a white-hot core, each spike brightest at its root and fading to its tip. With `shape` above 0.5 it is a tongue of flame on a card turned onto the element's Y axis (`zero_billboard_streak`), running from the middle of the card (the muzzle) to its tip along +Y, wavering at its edges and cooling toward the tip, on the half of the card between its middle and its +Y end. The petals are re-seeded every 1/30 s of world time, so a flash held for more than one frame flickers. The colour is the element's `data0` colour over the shape, plus a white `(1.0, 0.95, 0.85)` core scaled by the colour's brightest channel. The combat graphs beside it in `combat/` draw with it as `fxFlash`, additive. The `impact` graph draws two stars (`shape` 0) at the point of impact for three frames. The `muzzleFlash` graph draws three stars turned apart by their seeds (`shape` 0) and one tongue of flame down the bore (`shape` 1). Both colour the flash from an HDR ramp that falls to black over its short life. The `bench_mixed` scene places both graphs and the `main` scene places `muzzleFlash`. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour. | | `shape` | float | 0.0 | 0 draws the camera-facing star; above 0.5 draws the tongue along the element's Y axis. | | `vertexBoundsDilation` | float | 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.rgb` | The element's colour in linear HDR. | | `data1.x` | Seed that turns and re-sizes the petals; the shader adds a step every 1/30 s. |
▲ 0↑ born
✦
shader · born here
❒asset
# fxSmoke A puff of smoke on a card facing the camera (`zero_billboard`), for blending over the frame. It draws a soft, lumpy disc of three-octave value noise whose edge is pushed in and out by the noise, and as the puff ages the noise thins it from its wisps inward. It is lit by the ambient light plus the sun, wrapped around a sphere normal under the card so the side toward the sun is brighter. The colour is the element's colour times that light, and the alpha is the density times the element's opacity times `gain`. The combat graphs beside it in `combat/` draw with it as `fxSmoke`, transparent. The `impact` graph uses it for the burst of dust and grit off the struck surface (grit colour `(0.58, 0.53, 0.46)`, opacity falling from 0.55 to 0 over life), and the `muzzleFlash` graph for the puffs of smoke leaving the bore (grey `(0.56, 0.54, 0.52)`, opacity falling from 0.42 to 0). Both swell the card as it ages. The `bench_mixed` scene places both graphs and the `main` scene places `muzzleFlash`. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output alpha. | | `vertexBoundsDilation` | float | 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.rgb` | Smoke colour, multiplied by the lighting. | | `data1.x` | Seed: picks the puff's lumps. | | `data1.y` | Life, 0 at birth to 1 at death: thins the puff and drifts its noise. | | `data1.z` | Opacity. |
▲ 0↑ born
✦
shader · born here
❒asset
# fxSpark A spark: a card turned onto its element's motion and stretched along it (`zero_billboard_streak`), drawn as a white-hot core fading to its colour at the rim and tapering to a point at both ends. The width across the streak follows `1 - along^2`, so the card is widest at its middle; pixels outside that width are discarded. The body carries the element's colour, and a white core is added on the axis, scaled by the colour's brightest channel (capped at 4) times 0.35. The result times `gain` is added to the frame. The combat graphs beside it in `combat/` draw with it as `fxSpark`, additive. The `impact` graph uses it for the sparks thrown back off the struck surface, the `muzzleFlash` graph for the burning powder streaking out of the bore, and the `tracer` graph for the round's white-hot streak and the embers it sheds. Each graph turns the particle onto its velocity, lengthens its Y scale, and colours it from an HDR ramp that cools over its life. The `bench_mixed` scene places all three graphs and the `main` scene places `muzzleFlash`. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour. | | `vertexBoundsDilation` | float | 0.3 | 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` | The element's colour in linear HDR. |
▲ 0↑ born
·
procgraph · born here
❒asset
# tracer The glowing streak of a round in flight: a white-hot streak leaving the muzzle along -Z and burning out `distance` metres on, shedding embers that fall and cool behind it. Fire it at the muzzle with its -Z turned toward what the round hits, and `distance` the range to it: ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local function tracer(from, to) local dx, dy, dz = to[1] - from[1], to[2] - from[2], to[3] - from[3] local e = entity.spawn("tracer", { position = from, temporary = true }) e:lookAt(to) e.component.add("Generator", { graph = graph, playOn = "load", ending = "hold", params = { distance = math.sqrt(dx * dx + dy * dy + dz * dz) }, }) e.component.get("Generator").events.onFinished:connect(function() e:despawn() end) return e end ``` | Input | Default | What it does | |---|---|---| | `distance` | 40 | How far the round flies before it burns out, in metres: the range to what it hits. | | `speed` | 240 | How fast it flies, in metres per second. | | `width` | 0.04 | Width of the streak, in metres. | The streak runs back from the round for as far as it flies in a sixtieth of a second, and never behind the muzzle. It plays 45 frames at 60 fps (0.75 s). Each `distance` is its own set of frames: plays at one range share what the first one cooked.
▲ 0↑ born
·
procgraph · born here
❒asset
# dragon_breath A dragon's fire breath sweeping a courtyard: a jet of flame from the mouth, rolling dark smoke born where the flames die, and embers that drift and settle. The sweep is a function of time alone (yaw = 0.72 sin(2 pi t / 14), from world +Z toward +X), so the effect loops forever, and the Procgen Effects Showcase world's courtyard shader `flagstone_scorch` evaluates the same sweep to scorch the stones where the jet has just passed. The mouth stands at (0, 2.4, -9) in the generator's own space. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("dragon_breath", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` | Output | What it draws | |---|---| | `flame` | The flame jet, additive, `dragon_flame` shader | | `smoke` | The smoke the flames leave, `dragon_smoke` shader | | `embers` | Embers drifting down, additive, `dragon_ember` shader | In the Procgen Effects Showcase world's `fx_breath` scene, the `DragonBreathDirector` component on the same entity keeps the ground's scorch and a set of flickering lights in step with this graph's clock. The timeline has no end and plays at 60 fps.
▲ 0↑ born
✦
shader · born here
❒asset
# dragon_ember Glowing ember mote (additive billboard) for the `dragon_breath` graph. `data0 = (life, seed, size, 0)`. Flickers, cools from yellow-orange to dull red and fades as it settles. Each mote is a camera-facing card (`zero_billboard`) drawn as a soft disc. The flicker is `0.55 + 0.45 * sin(time * rate + seed * 40)` with a per-mote rate between 14 and 34 from the seed. The colour runs from `(6.0, 2.4, 0.5)` to `(1.2, 0.12, 0.01)` as heat `1 - 1.3 * life` falls; the mote fades in over the first 5 percent of its life and out between 0.6 and 1. It returns the colour times its coverage, for additive blending. The `dragon_breath` graph (`dragon/dragon_breath.procGraph`) draws its `embers` output with it, additive: embers shot out along the jet and kicked up where the flame hits the courtyard floor, on cards that shrink from 1.0 to 0.6 of their size over life. In the Procgen Effects Showcase world, the `fx_breath` scene plays that graph. All of its inputs arrive per particle on `data0`; properties.yaml holds `properties: []`. The shader includes `@builtin::shaderModules.billboard`. ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 to 1: drives the fades and the cooling. | | `data0.y` | Seed: the flicker's rate and phase. | | `data0.z` | Particle size, written by the graph. | | `data0.w` | 0. | ## Culling `vertexBoundsDilation` (float, default 0.1): how far the vertex hook moves a vertex past the mesh, in world units. The culling bounds grow by it, so a card turned to face the camera stays inside them where it reaches past the mesh it was drawn from.
▲ 0↑ born
✦
shader · born here
❒asset
# dragon_flame Additive camera-facing flame puff for the `dragon_breath` graph. `data0 = (life, seed, size, 0)`. Noise-carved blob that churns, erodes from the outside in and cools from yellow-white through orange to dull red over its life. Tuned for thousands of overlapping puffs (each carries a slice of the light). Each puff is a `zero_billboard` card turned by its seed and spun over its life in a direction the seed picks. A domain-warped four-octave value noise, scrolling with time, carves the blob's edge, and the threshold rises with life (`life * 0.85`) so the puff erodes from the rim inward. A faster inner churn layer mixes hotter and cooler tongues through the puff. Temperature combines youth, the dense core and both noise layers, then maps through a five-stop ramp from `(0.22, 0.012, 0)` to `(3.9, 2.3, 0.75)`. The puff fades in over the first 20 to 30 percent of its life (born thin at the nozzle) and out between 0.55 and 1, and its coverage is scaled by 0.27 (times a churn term) so each of the many stacked puffs carries a slice of the light. The `dragon_breath` graph (`dragon/dragon_breath.procGraph`) draws its `flame` output with it, additive: a fast bright jet and a slower, wider billow, on cards that grow from 0.55 to 2.6 of their size over life. In the Procgen Effects Showcase world, the `fx_breath` scene plays that graph. All of its inputs arrive per particle on `data0`; properties.yaml holds `properties: []`. The shader includes `@builtin::shaderModules.billboard`. ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 to 1: drives the spin, erosion, fades and cooling. | | `data0.y` | Seed: rotation, spin direction and rate, and the noise offset. | | `data0.z` | Particle size, written by the graph. | | `data0.w` | 0. | ## Culling `vertexBoundsDilation` (float, default 2.5): how far the vertex hook moves a vertex past the mesh, in world units. The culling bounds grow by it, so a card turned to face the camera stays inside them where it reaches past the mesh it was drawn from.
▲ 0↑ born
✦
shader · born here
❒asset
# dragon_smoke Alpha-blended rolling black smoke puff for the `dragon_breath` graph. `data0 = (life, seed, size, 0)`. Sooty and near-black, underlit orange by the fire only while young. Each puff is a `zero_billboard` card turned by its seed and slowly rotated over its life. A domain-warped four-octave value noise drifting with time breaks up a soft disc. The puff fades in over the first 18 percent of its life and out between 0.45 and 1, at a peak opacity of 0.62. Its colour is a near-black `(0.010, 0.009, 0.009)` lifted by noise into dark grey as it ages, plus an orange underglow `(1.6, 0.4, 0.08)`, weighted across the card by `0.5 - 0.5 * p.y` and toward its thin edge, that decays with `exp(-9 * life)` squared, so only young smoke catches the fire. The `dragon_breath` graph (`dragon/dragon_breath.procGraph`) draws its `smoke` output with it, transparent: smoke born where flame particles die, rolled by curl noise and drifting on a constant breeze, on cards that grow from 0.8 to 2.8 of their size over life. In the Procgen Effects Showcase world, the `fx_breath` scene plays that graph. All of its inputs arrive per particle on `data0`; properties.yaml holds `properties: []`. The shader includes `@builtin::shaderModules.billboard`. ## Lanes | Lane | Carries | |---|---| | `data0.x` | Life, 0 to 1: rotation, fades, greying and the underglow's decay. | | `data0.y` | Seed: rotation and noise offset. | | `data0.z` | Particle size, written by the graph. | | `data0.w` | 0. | ## Culling `vertexBoundsDilation` (float, default 2.5): how far the vertex hook moves a vertex past the mesh, in world units. The culling bounds grow by it, so a card turned to face the camera stays inside them where it reaches past the mesh it was drawn from.
▲ 0↑ born
·
procgraph · born here
❒asset
# launch A heavy-lift rocket's liftoff on one 36 s loop that drives the vehicle, the exhaust, the ground clouds, the sparks, the heat haze and the light together: | Graph time (mod 36) | What happens | |---|---| | 0 to 3 s | Quiet: the vehicle stands on the mount | | 3 to 8 s | Countdown: deluge steam bleeds from the trench mouths | | 10 s | Ignition: a flash, and the engines spool up to full thrust | | 12 s | The hold-downs release and the vehicle climbs on a pillar of fire | | 31.5 s | Engine cutoff, with the vehicle 1.3 km up, then the loop starts over | ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("launch", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` Its outputs are the vehicle in three materials (`hullWhite` its white body, `hullFoam` its orange foam-covered core, `hullDark` its dark bands and engines), the exhaust flame (`flameCards`), smoke and steam clouds (`smokeCards`, `steamCards`), spray off the deluge (`splashCards`), sparks (`sparkStreaks`), heat haze (`hazeCards`) and two lights (`lightFloor`, `lightPlume`). The timeline has no end and plays at 60 fps. In the Procgen Effects Showcase world, the `fx_launch` scene frames it with the `LaunchView` component.
▲ 0↑ born
◐
material · born here
❒asset
# rk_haze_mat Heat-shimmer material for the rocket launch. The `launch` graph beside it (`launch.procGraph`) resolves it by name and draws its `hazeCards` output with it: one card per particle of a 500-particle simulation fed from where the flame hits (36 per second at full thrust, living 1.2 to 2.4 s) and from the plume column (14 per second at full thrust, living 0.9 to 1.8 s). Each card grows from 0.7 to 1.4 times its size over its life, and its lane-0 colour comes from a ramp whose alpha rises to 0.9, falls to 0.5 and ends at 0; the shader reads that alpha as its strength. The graph's comment states that a `.material` asset is used here because the draw order matters for the haze. The `launch_fx` Generator entity runs the graph. The description in mat.yaml states that it is drawn before every other transparent surface, so it bends only the opaque scene and the flame and smoke drawn over it stay intact. Shader: `rk_haze` (`rk_haze.shader`). Its header: a large, transparent, camera-facing card that draws nothing of its own; it re-reads the scene colour behind it through a small, drifting noise offset, so the air above the flame trench and around the plume wobbles. The card's alpha follows how much the bent read differs from the straight one, so it is visible at edges in the opaque scene and blends away over flat sky or ground. Render state (the `render` block of mat.yaml): `queue: 2600`, `type: transparent` (alpha blend), `cull: none`, `depth_write: false`. ## Properties - `strength: 16.0`: scale of the noise offset, in pixels, applied to the scene-colour read (default 38.0). - `edge_gain` keeps its default, 6.0: multiplier that turns the colour difference into alpha.
▲ 0↑ born
✦
shader · born here
❒asset
# rk_flame Rocket exhaust flame: an additive, camera-facing card (`zero_billboard`) whose shape is eaten away by animated fBm, so a stack of them reads as one turbulent, white-hot plume. Each card is a disc rotated by its own random angle, and a four-octave value noise scrolls through it with time at a per-card speed so the surface churns. The young flame is nearly a solid disc; as life rises the noise erodes it more (erosion from 0.25 to 0.95), until the old flame shreds. A hot inner bloom fades out over the card's life. The colour is the lane colour times the shape and bloom, its opacity and `gain`, returned with alpha 1 for additive blending. The `launch` graph (`launch/launch.procGraph`) draws two outputs with it, additive: `flameCards` (`gain` 1.0), the exhaust from the six nozzles, each a tight blinding core wrapped in a wider turbulent sheath, plus the ignition flash in the trench, and `splashCards` (`gain` 0.85), the fire splashing sideways where the plume hits the ground. Both colour the cards from an HDR ramp that runs from white-hot `(20, 18, 14)` to a dark red that fades to nothing, and grow the cards over life. In the Procgen Effects Showcase world, the `fx_launch` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (minimum 0). | | `vertexBoundsDilation` | float | 14 | 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, already walked along the particle's life by the graph. | | `data0.a` | Opacity, multiplied into the colour. | | `data1.x` | Life, 0 to 1: sets the erosion and fades the inner bloom. | | `data1.y` | Per-particle random 0 to 1: the card's rotation, noise offset and churn speed. | | `data1.z` | Named a stretch or turbulence hint in the shader header; the `launch` graph writes 0 here for its flame cards. |
▲ 0↑ born
✦
shader · born here
❒asset
# rk_haze Heat shimmer. A large, transparent, camera-facing card (`zero_billboard`) that draws the scene behind it again through a small, drifting offset, so the air above the flame trench and around the plume visibly wobbles. Two value-noise fields, sampled from the card's world position and rising with time, give the offset; it is scaled by `strength`, by the lane's strength and by a soft round mask, and read through `zero_scene_color_refract`. The scene colour holds the opaque scene only, so the card is opaque only where bending that scene changes the picture: the difference between the bent and the straight read, times `edge_gain`, sets the alpha. Over flat sky or ground the card is invisible. The `rk_haze_mat` material uses it with `strength` 16, in the transparent queue at 2600, with culling off and depth writes off; its description states it is drawn before every other transparent surface so it bends only the opaque scene. The `launch` graph (`launch/launch.procGraph`) draws its `hazeCards` output with that material: shimmer cards born where the exhaust hits the ground and trailing the climbing vehicle, their lane strength rising to 0.9 early in life and then fading out. In the Procgen Effects Showcase world, the `fx_launch` scene plays the graph. The shader includes `@builtin::shaderModules.billboard` and `zero::scene_color`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `strength` | float | 38.0 | Scale of the refraction offset (minimum 0). | | `edge_gain` | float | 6.0 | Multiplies the colour change the bend causes to give the card's alpha (minimum 0). | | `vertexBoundsDilation` | float | 22 | 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.a` | Strength 0 to 1, walked along the particle's life. | | `data1.y` | Per-particle random value: offsets the noise. |
▲ 0↑ born
✦
shader · born here
❒asset
# rk_smoke Billowing smoke or steam puff: an alpha-blended, camera-facing card (`zero_billboard`). A soft body is broken up by two layers of four-octave value noise, so overlapping puffs merge into one rolling mass. Each card is rotated by its random value and turns slowly over life. The density's gradient gives a lumpy normal, lit by the sun direction projected into the card's plane and un-rotated so the light stays fixed on screen. The lighting uses fixed values: a cool sky fill `(0.20, 0.22, 0.28)` plus the sun's normalised colour, scaled by `sun_gain` and `brightness`, with thick middles shadowed by their own mass. A warm exhaust underglow `(3.0, 1.05, 0.28)`, scaled by the lane's heat and `glow_gain`, is strongest on the underside and where the puff is thin. The alpha is the density times the lane opacity and `opacity`, faded against the scene behind it over `depth_fade` and faded in over `ground_fade` above world height 0. The `launch` graph (`launch/launch.procGraph`) draws two outputs with it, transparent: `smokeCards`, the smoke born where the exhaust hits the ground, pushed out of the trench mouths and trailing the climbing vehicle (`sun_gain` 0.8, `depth_fade` 2.5, `ground_fade` 0.6, heat 1.0 at birth falling to 0 by half its life), and `steamCards`, the white deluge steam during the countdown (`sun_gain` 0.8, `glow_gain` 0.8, `depth_fade` 2.0, `ground_fade` 0.5, heat 0.7 falling to 0 by 0.4 of its life). In the Procgen Effects Showcase world, the `fx_launch` scene plays the graph. The shader includes `@builtin::shaderModules.billboard` and `zero::scene_depth`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `opacity` | float | 1.0 | Multiplies the alpha (minimum 0). | | `sun_gain` | float | 1.0 | Multiplies the sun term (minimum 0). | | `glow_gain` | float | 1.0 | Multiplies the exhaust underglow (minimum 0). | | `depth_fade` | float | 1.5 | Distance over which the puff fades into the scene behind it (minimum 0). | | `ground_fade` | float | 0.35 | World height over which the puff fades in above height 0 (minimum 0.01). | | `brightness` | float | 1.0 | Multiplies the lit colour (minimum 0). | | `vertexBoundsDilation` | float | 15 | 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` | Tint. | | `data0.a` | Opacity; also scales the underglow. | | `data1.x` | Life, 0 to 1: the card's slow turn. | | `data1.y` | Random 0 to 1: rotation and noise offset. | | `data1.z` | Heat 0 to 1: how much exhaust light the puff catches. |
▲ 0↑ born
✦
shader · born here
❒asset
# rk_spark Spark and burning-debris streak. The card's Y axis lies along the particle's motion (`zero_billboard_streak`) and the graph stretches it by speed, so the fragment draws a thin line along the card, brightest at the head (+Y) and fading toward the tail, plus a bright spot at the head. The colour is the lane colour times that shape, the lane opacity and `gain`, returned with alpha 1 for additive blending. The `launch` graph (`launch/launch.procGraph`) draws its `sparkStreaks` output with it (additive, `gain` 1.4): sparks and burning chunks thrown from where the exhaust hits the ground, bouncing off the scene, stretched from 1.5 to 9 times their size over speeds 0 to 30, and coloured from an HDR ramp that cools from `(12, 9, 4.5)` to dark red over life. In the Procgen Effects Showcase world, the `fx_launch` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (minimum 0). | | `vertexBoundsDilation` | float | 0.3 | 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. | | `data0.a` | Opacity, multiplied into the colour. |
▲ 0↑ born
·
procgraph · born here
❒asset
# arcane_rift A rift tearing open in the ground: a glowing mouth along a crack in the earth, cracks branching out from it, rubble heaving up, sparks and streaks climbing out of it, motes drifting above and a plume rising from it. It is centred on the generator's origin with its long axis along x and the ground at y = 0. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("arcane_rift", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` | Input | Default | What it does | |---|---|---| | `intensity` | 1 | Brightness of everything that glows: the mouth, cracks, sparks, streaks, motes and plume (0 to 4). | | Output | What it draws | |---|---| | `mouth` | The glowing opening, `rift_core` shader | | `cracks` | The cracks branching out across the ground, `rift_crack` shader | | `rubble` | Rubble around it, `rift_rock` shader, moved by the `rift_rubble` compute shader | | `sparks` | Sparks thrown from the mouth, `rift_streak` shader | | `streaks` | Streaks climbing out of it, `rift_streak` shader | | `motes` | Motes drifting above it, `rift_mote_cluster` shader, moved by the `rift_motes` compute shader | | `plume` | The plume rising from it, `rift_plume` shader | The timeline has no end and plays at 60 fps.
▲ 0↑ born
·
computeshader · born here
❒asset
# rift_motes One step of the arcane mote swarm, run as a `sim.shader` solver with a neighbour grid. Motes swirl around the rift through a rolling vortex ring stirred by turbulence, and keep apart through grid-based separation, so the swarm streams together with its motes kept apart. It runs one invocation per mote in workgroups of 64. For each mote the shader builds a desired velocity from four parts: - a swirl around the vertical axis through the origin, `swirl * (0.45 + 1.4 * exp(-0.35 * rho))`, fastest near the axis; - a poloidal roll around the ring core at radius `coreR` and height `coreH`: up on the inside, out over the top, down at the outer edge, at a rate set by `rollRate`; - a smooth turbulence from summed sines of position and time; - a pull back toward the ring core for any mote farther than `shell` from it, and a lift for any mote below height 0.2. It then visits every mote in the 27 grid cells around it and adds a push away from each neighbour closer than `radius`, weighted by `(1 - distance / radius)^2`. The velocity eases toward the desired one at a rate of `1 - exp(-1.6 * dt)`, takes the push times `separate * dt`, is capped at 4.5 units per second, and moves the mote by `velocity * dt`. ## Bindings | Binding | Access | What it holds | |---|---|---| | `P` | read_write | Positions, three floats per mote; the shader writes the new position. | | `prev_P` | read | Positions at the start of the step, read for the mote itself and for its neighbours. | | `v` | read_write | Velocities, three floats per mote; read and written back. | | `gcfg` | read | Grid configuration, used by `zero_grid_cell` and `zero_grid_range`. | | `grange` | read | Per-cell ranges into `gorder`, used by `zero_grid_range`. | | `gorder` | read | Mote indices sorted by grid cell; the separation loop reads neighbours from it. | The grid helpers come from `#include "@builtin::systems.procgen.grid"`. ## Parameters | Parameter | Type | Default | Meaning | |---|---|---|---| | `count` | int | 0 | Number of motes. | | `dt` | float | 0.0166667 | Step length in seconds. | | `time` | float | 0.0 | Solver time in seconds; drives the turbulence. | | `radius` | float | 0.35 | Separation radius. | | `separate` | float | 7.0 | Strength of the separation push. | | `coreR` | float | 2.8 | Radius of the vortex ring's core from the vertical axis. | | `coreH` | float | 1.9 | Height of the vortex ring's core. | | `shell` | float | 3.2 | Distance from the ring core beyond which motes are pulled back. | | `swirl` | float | 1.7 | Speed of the swirl around the vertical axis. | | `rollRate` | float | 0.45 | Rate of the poloidal roll. | ## Dispatch The `arcane_rift` graph (`rift/arcane_rift.procGraph`) dispatches it from its `swarm` node, a `sim.shader` over 900 points seeded in a cylinder of radius 4.2 and height 3.4, with a `v` (Vec3) attribute, `neighborRadius` 0.75 and uniforms `radius` 0.75, `separate` 5, `coreR` 2.5, `coreH` 1.7, `shell` 1.9, `swirl` 1.5 and `rollRate` 0.5. Each of those 900 leaders is drawn as a cluster of eight motes by `rift_mote_cluster`. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph.
▲ 0↑ born
·
computeshader · born here
❒asset
# rift_rubble Analytic, per-chunk periodic motion for rubble orbiting the arcane rift, run as a `sim.shader` solver. Every chunk's state is a function of the solver time alone, periodic per chunk, so the loop is seamless: a chunk grows in while still buried, shudders, rips free, spirals up into orbit, climbs, then crumbles to nothing glowing hot, and is buried again for its next cycle at a new spot around the rift. It runs one invocation per chunk in workgroups of 64. Each chunk hashes its index into its own values: a period of 0.8 to 1.2 times `period`, a phase offset, a starting angle, the radius where it tears loose (1.5 to 4.1), its orbit radius (2.1 to 4.0), the height it climbs to (1.4 to 4.6), a size, an orbit speed and a tumble axis. Through each cycle its phase passes four stages: emerging (0 to 0.08), ripping free (0.08 to 0.26), climbing (0.22 to 0.9) and crumbling (0.84 to 0.985). The orbit is stretched 1.2 times along X, larger chunks orbit and spin more slowly, and the chunk bobs gently once free. ## Bindings | Binding | Access | What it holds | |---|---|---| | `P` | read_write | Positions, three floats per chunk; written. | | `orient` | read_write | Orientation quaternion per chunk (`vec4f`); written as a rotation about the chunk's axis. | | `scale` | read_write | Scale, three floats per chunk; written. It grows in over the first 5 percent of the cycle and falls to zero as the chunk crumbles. | | `data0` | read_write | Per-chunk lane (`vec4f`); written as (heat, seed, cycle phase, 0). | Heat is `0.25 + 1.2 * rip * (1 - climb) * emerge + 2.5 * crumble`: the seams flare as the chunk rips free and burn brightest as it crumbles. ## Parameters | Parameter | Type | Default | Meaning | |---|---|---|---| | `count` | int | 0 | Number of chunks. | | `time` | float | 0.0 | Solver time in seconds. | | `period` | float | 16.0 | Base length of one cycle in seconds. | | `spin` | float | 0.55 | Base tumble rate. | ## Dispatch The `arcane_rift` graph (`rift/arcane_rift.procGraph`) dispatches it from its `orbiting` node, a `sim.shader` over 72 points on a disc, with `orient` (Vec4), `scale` (Vec3) and `data0` (Vec4) attributes and uniforms `period` 17 and `spin` 0.55. The graph draws each chunk as a noise-displaced, subdivided octahedron with the `rift_rock` material, casting shadows; `rift_rock` reads heat from `data0.x` and per-chunk variation from `data0.y`. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph.
▲ 0↑ born
✦
shader · born here
❒asset
# rift_core The mouth of an arcane rift on a flat ground plane: a jagged, breathing, lens-shaped tear with a white-hot rim, a parallax churning abyss inside, and a halo of light on the ground. It uses a premultiplied blend: the abyss covers the ground (alpha 1) and the halo only adds light (alpha 0). The plane's UV is mapped to metres through `plane_size_x` and `plane_size_z`. The tear's outline is a lens `half_length` long and `half_width` wide each side of its centre line, fullest in the middle and pinched at the tips, with a jagged edge from `rift_noise` fBm that differs on each lip and grinds slowly with time, and a slow breathing of its width. Inside, the abyss is three layers of swirling, twisted noise seen at depths 0.25, 0.9 and 2.2 below the surface along the view ray, so it reads as a shaft going down; the layers mix `deep_color` and `mid_color` and carry thin `hot_color` filaments, with a darker core along the centre line. The rim is a flickering white-hot lip over a `hot_color` sheath, and outside it a `mid_color` halo with licking tongues of light spreads over the ground. The whole result fades out toward the plane's edges and is scaled by `gain`. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) draws its `mouth` output with it through `coreMat` (premultiplied, culling off, depth writes off) on a 7 by 4 plane lifted 0.015 above the ground, with `gain` wired to the graph's `intensity` input. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph. The shader includes `rift_noise` with `#include "rift_noise"`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (range 0 to 20). | | `half_length` | float | 2.1 | Half-length of the tear along X, in metres of the plane. | | `half_width` | float | 0.62 | Half-width of the tear at its fullest. | | `plane_size_x` | float | 7.0 | Size of the plane along X, mapping UV to metres. | | `plane_size_z` | float | 4.0 | Size of the plane along Z, mapping UV to metres. | | `deep_color` | color | [0.02, 0.0, 0.08, 1] | Darkest colour of the abyss. | | `mid_color` | color | [0.5, 0.09, 1.5, 1] | Swirl colour of the abyss, tint of the rim and colour of the ground halo. | | `hot_color` | color | [1.2, 1.6, 4.0, 1] | Colour of the abyss filaments and the rim's sheath. |
▲ 0↑ born
✦
shader · born here
❒asset
# rift_crack An additive glowing ground crack for ribbons from `geometry.ribbon`: a thin white-hot seam inside a coloured glow, with energy surges running outward from a centre (in world space) and fading with distance (`reach`). On the ribbon `uv.x` runs along the crack and `uv.y` across it. The seam is a tight Gaussian across the ribbon and the glow a wider one in `glow_color`. Two trains of surges travel outward from `center` at different speeds, a slow noise flicker plays over them, and the brightness falls off as `exp(-distance / reach)`. Fragments dimmer than 0.002 are discarded. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) draws its `cracks` output with it through `crackMat` (additive, culling off, depth writes off). The cracks are ribbons 0.5 wide laid along eleven trunk lines leaving the tear's rim, wandering on curl noise and forked by `curve.branch` into three generations that narrow with each fork. The graph wires `gain` to its `intensity` input and leaves the other properties at their defaults; the default `center` (-147.5, 0, 148) is the world position of the `ArcaneRift` entity in the Procgen Effects Showcase world's `fx_rift` scene. The shader includes `rift_noise` with `#include "rift_noise"`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output (range 0 to 20). | | `center` | float3 | [-147.5, 0, 148] | World position the surges run out from and the falloff is measured from (only x and z are read). | | `reach` | float | 3.5 | Distance scale of the falloff, `exp(-distance / reach)`. | | `glow_color` | color | [1.0, 0.25, 3.2, 1] | Colour of the glow around the seam. |
▲ 0↑ born
✦
shader · born here
❒asset
# rift_mote_cluster Draws a cluster of glowing motes per element. The mesh carries degenerate quads (all four corners at one point, told apart by their UV) on a unit sphere; the vertex stage orbits each around its own axis and expands it to a camera-facing sprite. The element's scale sets how far the cluster spreads, so a simulated swarm of a thousand leaders draws as thousands of motes for the cost of a thousand renderables. Lane 0 is the HDR colour and opacity; `size` is the sprite size in metres. In `vertex_clip` each sub-mote takes a stable id from where it sits in the cluster mesh and hashes it into three values. It circles a per-mote axis at 0.35 to 1.25 radians per second, at a radius that breathes between 0.2 and 1.0 of its rest position, is placed through the element's origin, axes and scale, and is expanded into a sprite `size` times 0.55 to 1.45 across. The three hashes pass to the fragment as the vertex colour. The fragment draws a core and halo that twinkle at a per-mote rate of 1.5 to 7.5 radians per second, leans each sub-mote's hue between a cool `(0.75, 0.85, 1.25)` and a warm `(1.25, 0.8, 1.0)` tint of the cluster's colour, and whitens the core. It returns the colour times its coverage times `gain`, with the coverage as alpha. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) draws its `motes` output with it through `moteMat` (additive, culling off, depth writes off, `size` 0.055, `gain` wired to the graph's `intensity` input). The 900 leaders come from the `rift_motes` solver; each draws a cluster mesh of eight zero-size quads placed on a sphere shell, at a random spread of 0.6 to 1.0, coloured from a blue-violet-pink ramp by a random hue. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph. The shader includes `rift_noise` with `#include "rift_noise"`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (range 0 to 50). | | `size` | float | 0.06 | Sprite size of each sub-mote in metres, before its 0.55 to 1.45 variation (range 0 to 1). | | `vertexBoundsDilation` | float | 2.1 | 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 of the cluster. | | `data0.a` | Opacity. |
▲ 0↑ born
·
shadermodule · born here
❒asset
# rift_noise Precision-safe integer-hash value noise and fbm (2D, 3D, and y-periodic variants for seamless time scrolling) shared by the arcane rift shaders. The hashes are integer PCG hashes of the lattice cell, so they stay crisp however large the coordinates grow, and every 2D noise can wrap along y with a period in lattice cells, so a field scrolled by time loops seamlessly. The interpolation is the smoothstep curve `f * f * (3 - 2 * f)`. A shader includes it with: ```wgsl #include "rift_noise" ``` The asset folder holds the same source as `module.wgsl` and `init.wgsl`. ## Functions | Function | Arguments | Returns | |---|---|---| | `rn_pcg(v)` | `v: u32` | A PCG-hashed `u32`. | | `rn_hash2(c)` | `c: vec2i`, a lattice cell | A hash of the cell as an `f32` between 0 and 1. | | `rn_hash3(c)` | `c: vec3i`, a lattice cell | A hash of the cell as an `f32` between 0 and 1. | | `rn_noise2p(p, period)` | `p: vec2f`, `period: i32` | 2D value noise between 0 and 1. With `period` above 0, the lattice wraps along y every `period` cells. | | `rn_noise2(p)` | `p: vec2f` | `rn_noise2p(p, 0)`: 2D value noise with `period` 0. | | `rn_fbm2(p)` | `p: vec2f` | Five octaves of `rn_noise2` with amplitudes 0.5, 0.25, 0.125 and so on; each octave rotates and scales the point by the matrix (1.6, 1.2, -1.2, 1.6) and offsets it. | | `rn_fbm2p(p, period)` | `p: vec2f`, `period: i32` | Four octaves of `rn_noise2p`, the frequency and the period doubling each octave so every octave wraps along y with the base period. | | `rn_noise3(p)` | `p: vec3f` | 3D value noise between 0 and 1. | | `rn_wrap(t, period)` | `t: f32`, `period: f32` | `t` wrapped into [0, period), to keep a time-scrolled coordinate small. | ## Used by - `rift_core`: `rn_fbm2` and `rn_noise2` for the tear's jagged edge, the abyss swirl, the rim flicker and the halo tongues. - `rift_crack`: `rn_wrap` for the surge trains and `rn_noise2` for the flicker. - `rift_mote_cluster`: `rn_hash3` for each sub-mote's id and `rn_wrap` for its orbit and twinkle. - `rift_plume`: `rn_wrap` and `rn_fbm2p` with a period of 16 for the climbing wisps.
▲ 0↑ born
✦
shader · born here
❒asset
# rift_plume A rising column of arcane light for the rift: an upright card turned about the world Y axis toward the camera (`zero_billboard_axis`), filled with climbing, twisting wisps, brightest at the base and fading into the dark. Lane 0 is the HDR colour and opacity, lane 1.x a per-card phase. Across the card the column is a Gaussian body that narrows from full width at the base to 0.3 of it at the top and sways on a sine that climbs with time. Two layers of `rn_fbm2p` noise, periodic along y with a period of 16 and scrolled with `rn_wrap`, stream upward through it, so the loop is seamless. The column fades in over the bottom 8 percent, falls off as `(1 - y)^2.2` toward the top, and carries an extra glow right at the base. It returns the colour times its coverage times `gain`, with the coverage as alpha. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) draws its `plume` output with it through `plumeMat` (additive, culling off, depth writes off, `gain` wired to the graph's `intensity` input): four cards spaced along X from -0.9 to 0.9 at height 3.6, each 2.2 to 3.4 wide and 7.5 tall, coloured (1.1, 0.4, 3.0) at opacity 0.5, with a random phase each. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph. The shader includes `@builtin::shaderModules.billboard` and `rift_noise`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (range 0 to 20). | | `vertexBoundsDilation` | float | 1.7 | 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. | | `data0.a` | Opacity. | | `data1.x` | Per-card phase; the shader multiplies it by 10 and offsets the sway and the wisps with it. |
▲ 0↑ born
✦
shader · born here
❒asset
# rift_rock Torn basalt rubble with glowing arcane seams: lit PBR stone whose seam emission follows lane 0.x (heat), while lane 0.y varies the pattern per chunk. The fragment builds a `PbrSurface` and shades it with `zero_pbr_shade` from `@builtin::shaderModules.pbr_shading`. The pattern is 3D value noise over the mesh's own UV (scaled 6 by 3) plus the chunk's variation, so it stays fixed on the chunk as it tumbles. One noise layer, folded about its middle and raised to the 30th power, draws thin seams; a second varies the stone's brightness and roughness (0.73 to 0.88). The albedo is `base_color` darkened along the seams. The emission is `glow_color` times the seam, the heat and a flicker at 9 radians per second, plus a faint constant seam glow and a dim glow on downward-facing surfaces. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) draws its `rubble` output with it through `rockMat`, on noise-displaced, subdivided octahedra that cast shadows. The `rift_rubble` compute shader moves the chunks and writes their `data0` as (heat, seed, cycle phase, 0). In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `base_color` | color | [0.09, 0.085, 0.095, 1] | Stone colour before noise and seams. | | `glow_color` | color | [1.0, 0.3, 3.0, 1] | Colour of the seam and underside glow. | ## Lanes | Lane | Carries | |---|---| | `data0.x` | Heat: brightness of the seam glow. | | `data0.y` | Per-chunk variation: offsets the noise pattern and the flicker phase. |
▲ 0↑ born
✦
shader · born here
❒asset
# rift_streak An additive energy streak for procgen particles: a velocity-aligned billboard card (`zero_billboard_streak`, turned onto the element's `orient` and stretched by its `scale.y`) drawn as a hot filament with a soft sheath. Lane 0 carries the HDR colour and opacity, lane 1.x a shimmer phase. Along the card the streak tapers at both ends and is fuller toward the head; across it a tight Gaussian core sits inside a wider sheath. The core bleeds toward white, and a shimmer at 37 radians per second plays over the whole streak. It returns the colour times its coverage times `gain`, with the coverage as alpha. The `arcane_rift` graph (`rift/arcane_rift.procGraph`) builds `streakMat` from it (additive, culling off, depth writes off, `gain` wired to the graph's `intensity` input) and draws two outputs with it: `sparks`, the bursts that arc out of the tear and bounce on the ground plus the smaller sparks they throw, and `streaks`, the energy streaks spiralling up out of the rift. The graph turns each particle onto its velocity, stretches it by speed, colours it from a violet and blue HDR ramp over its life, and writes a random value into lane 1. In the Procgen Effects Showcase world, the `fx_rift` scene plays the graph. The shader includes `@builtin::shaderModules.billboard`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `gain` | float | 1.0 | Multiplies the output colour (range 0 to 50). | | `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. | | `data0.a` | Opacity. | | `data1.x` | Per-element shimmer phase, 0 to 1 of a turn. |
▲ 0↑ born
·
shadermodule · born here
❒asset
# fx_noise Procedural noise for effect shaders, as WGSL other shaders include with `#include "fx_noise"`: integer hashes, value and gradient noise in 2D and 3D, fBm and ridged fBm over them, curl noise, and worley (cellular) noise that returns the distance to the nearest feature point and that cell's id. The functions are pure math over their arguments, so a material's fragment shader and a compute shader can both include it and read the same field. Every generator takes an explicit `seed`, so one shader draws several uncorrelated fields from the same coordinates. The hashes mix integers, so a value is the same bit pattern wherever it runs; the float entry points hash a float's bit pattern, with `0.0` and `-0.0` folded together. ```wgsl #include "fx_noise" ``` | Function | Returns | |---|---| | `fx_hash11(x)`, `fx_hash21(p)`, `fx_hash31(p)` | a stable value in [0, 1) for a number or point | | `fx_value_noise2(p, seed)`, `fx_value_noise3(p, seed)` | smooth value noise in [0, 1) | | `fx_gradient_noise2(p, seed)`, `fx_gradient_noise3(p, seed)` | gradient (Perlin-style) noise in [-1, 1], exactly 0 at every integer point | | `fx_fbm2(p, octaves, lacunarity, gain, seed)`, `fx_fbm3(...)` | fractal sum of gradient noise in [-1, 1]: clouds, smoke, rock | | `fx_ridged_fbm3(p, octaves, lacunarity, gain, seed)` | ridged fractal noise in [0, 1]: cracks, crags, veins | | `fx_curl_noise3(p, seed)` | a divergence-free flow vector: swirling smoke and dust | | `fx_worley2(p, seed)`, `fx_worley3(p, seed)` | `{ dist, cell, id }` of the nearest feature point: foam cells, stone, sparkle | | `fx_worley_fbm2(p, octaves, lacunarity, gain, seed)` | fractal cellular noise in [0, 1] | ## Arguments - `p` is an `f32`, `vec2f` or `vec3f` coordinate, matching the function's dimension. - `seed` is a `u32`. - `octaves` is a `u32`, clamped to 1 through `FX_FBM_MAX_OCTAVES` (12). Each octave multiplies the frequency by `lacunarity` and the amplitude by `abs(gain)`, and the fBm functions divide by the summed amplitudes, which keeps the stated range for any gain. Octave `i` uses seed `seed + i * 1013`. ## Building blocks The module also exports the pieces the generators are built from: | Function or item | What it is | |---|---| | `fx_hash_u32(x)`, `fx_hash_u2(x, y)`, `fx_hash_u3(x, y, z)` | Integer avalanche hashes of one, two or three `u32` words, returning a `u32`. | | `fx_unorm(h)`, `fx_snorm(h)` | A hashed `u32` as an `f32` in [0, 1) or [-1, 1), from its top 24 bits. | | `fx_bits(x)` | The `u32` bits of an `f32`, with negative zero folded onto positive zero. | | `fx_hash22(p)`, `fx_hash33(p)` | Two or three decorrelated values in [0, 1) for a 2D or 3D point. | | `fx_lattice_u2(cell, seed)`, `fx_lattice_u3(cell, seed)` | The hashed `u32` a seeded integer lattice corner (`vec2i` or `vec3i`) carries. | | `fx_lattice21(cell, seed)`, `fx_lattice31(cell, seed)` | That corner's value in [0, 1); `fx_value_noise2` at an integer point equals `fx_lattice21` of that point. | | `fx_fade(t)` | The quintic fade `t^3 * (t * (6t - 15) + 10)` used to interpolate across a cell. | | `fx_gradient2(cell, seed)`, `fx_gradient3(cell, seed)` | The unit gradient a seeded lattice corner carries; the 3D one is spread evenly over the sphere. | | `fx_curl_potential3(p, seed)` | The three-component potential `fx_curl_noise3` takes the curl of, by central differences over `FX_CURL_EPSILON` (0.05). | | `fx_cell_point2(cell, seed)`, `fx_cell_point3(cell, seed)` | Where a cell's feature point sits inside the cell, in [0, 1) per axis. | | `fx_cell_id2(cell, seed)`, `fx_cell_id3(cell, seed)` | The id in [0, 1) a cell is tinted by. | | `FxWorley2`, `FxWorley3` | The worley result: `dist` (`f32`), `cell` (`vec2i` or `vec3i`) and `id` (`f32`). | | `FX_TAU` | 2 pi. | `fx_worley2` searches the 3 by 3 cells around the sample and `fx_worley3` the 3 by 3 by 3 cells. `fx_worley_fbm2` sums `1 - dist`, clamped to [0, 1], over its octaves, so feature points read as peaks. ## Used by The waterfall (`wf_particle`, `wf_pool`, `wf_rock`, `wf_sheet`) and wall blast (`blast_puff`, `blast_shock`, `blast_stone`) shaders in this package draw their foam, mist, rock, dust and debris from it, and so does the Procgen Effects Showcase world's `blast_ground`.
▲ 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
✦
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_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
# storm_stone Procedural rain-soaked ashlar masonry in world space: courses of blocks with per-block tint, bevelled joints, weathering streaks, lichen and running water that darkens the stone and drops its roughness. It is an engine-lit `surface()` shader that fills a `PbrSurface`. The shader projects each face onto the plane it lies in: XZ where the normal is within about 44 degrees of vertical (`|n.y| > 0.72`), otherwise the vertical plane facing X or Z, and scales the result by `scale`. Courses are 0.46 high with blocks 0.8 to 1.5 wide and a random offset per course. Each block is a slightly rounded, chiselled slab with a dark joint; the height of the slab, the chisel and a fine grain bend the normal by `bump`. Joints and bump fade out where the pattern gets too fine for the screen (measured with `fwidth`), where the colour also eases toward a flat grey `(0.21, 0.20, 0.20)`. The stone is a cool grey with warm variation per block, dark vertical stains hang from the joints, and green lichen and grime creep up from the plinth below world height 7. Water sheets down the walls in streaks that slide with time: wetness is 0.7 of `wet` between the streaks and rises along them, darkening the albedo by up to half and dropping roughness from 0.9 to 0.16 (1.35 times that in the joints). Reflectance is 0.6 and occlusion is lower in the joints. The `tower` graph (`storm/tower.procGraph`) builds the stone keep of the Procgen Effects Showcase world's `fx_storm` scene with it through `stoneMat`, with `scale` 1.0, `wet` 0.9 and `bump` 1.0. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `scale` | float | 1.0 | Scale of the masonry pattern; larger values give smaller blocks (range 0.2 to 4). | | `bump` | float | 1.0 | Strength of the bump normal (range 0 to 4). | | `wet` | float | 0.85 | How soaked the stone is, 0 dry to 1 streaming. |
▲ 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
·
procgraph · born here
❒asset
# 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. ```lua -- `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" }) ``` | Output | What it draws | |---|---| | `rain` | The falling rain, `storm_streak` shader | | `splash` | Splashes where rain lands, `storm_streak` shader | | `sheets` | Sheets of rain sweeping through, `storm_sheet` shader | | `bolt1` to `bolt4` | The lightning bolts, `lightning_bolt` shader | | `sparks` | Sparks where strikes land, `storm_streak` shader | | `smoke` | Smoke 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.
▲ 0↑ born
·
procgraph · born here
❒asset
# tower A lone stone keep: a plinth, a square shaft, a corbelled gallery with a crenellated parapet, a round turret under a conical roof and an iron finial, 48.6 m to the tip of the finial. It is built from boxes, cylinders, a cone and a sphere joined into one entity output: the stone draws with the `storm_stone` shader and the finial with dark metal. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("tower", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph }) ``` The output `keep` is the tower. It stands at the centre of the Procgen Effects Showcase world's `fx_storm` scene.
▲ 0↑ born
◐
material · born here
❒asset
# wf_pool_mat Water material for the plunge pool at the foot of the waterfall. `waterfall/wf_water.procGraph` builds the still and falling water of the waterfall and assigns this material to one of its parts by name; the graph's header states that the water materials are `.material` assets so the Model receives their blend, cull and depth-write state. The `WaterfallWater` Generator entity in the Procgen Effects Showcase world's `fx_falls` scene runs that graph. This material goes on `pool_skin`: a 21 x 18.5 m grid at height -0.35, centred 4.4 m on the -z side of the waterfall's z (Z0 - 4.4). Shader: `wf_pool` (`waterfall/shaders/wf_pool.shader`). Its README: plunge-pool water with travelling ripples, churn turbulence, two-phase radial foam flow, depth-driven shore and rock foam, fresnel sky reflection and sun glitter, and a refracted bed. It reads the scene depth already drawn under the surface to choose between a lighter and a darker water colour and to put foam where the water meets the bed and rocks; alpha runs from 0.55 to 1 with that depth term, plus foam. Render state: `blend: alphaBlend`, `cull: none`, `depth_write: false`. ## Properties - `origin_x: 0` and `origin_z: 42`: world x and z the shader measures positions from. 42 is the `Z0` constant `waterfall/wf_water.procGraph` places the waterfall at. - `impact_x: 0` and `impact_z: -3.5`: the plunge point, relative to the origin (default impact_z -3.4). The water churns around it and the foam flows outward from it. - `churn_radius: 3.7`: size of the churned zone around the plunge point, as the falloff `exp(-(d / churn_radius)^2)` (default 3.6). - `foam: 1`: blend weight of the foam over the water colour (default 1.0).
▲ 0↑ born
◐
material · born here
❒asset
# wf_river_mat Water material for the river that runs to the waterfall's lip. `waterfall/wf_water.procGraph` builds the still and falling water of the waterfall and assigns this material to one of its parts by name; the graph's header states that the water materials are `.material` assets so the Model receives their blend, cull and depth-write state. The `WaterfallWater` Generator entity in the Procgen Effects Showcase world's `fx_falls` scene runs that graph. This material goes on `river_skin`: a 7.2 x 13 m grid at the lip height (21.9), centred 6.9 m on the +z side of the waterfall's z (Z0 + 6.9). Shader: `wf_pool` (`waterfall/shaders/wf_pool.shader`). Its README: plunge-pool water with travelling ripples, churn turbulence, two-phase radial foam flow, depth-driven shore and rock foam, fresnel sky reflection and sun glitter, and a refracted bed. It reads the scene depth already drawn under the surface to choose between a lighter and a darker water colour and to put foam where the water meets the bed and rocks; alpha runs from 0.55 to 1 with that depth term, plus foam. The river uses the same shader as the plunge pool (`wf_pool_mat`) with its own values. Render state: `blend: alphaBlend`, `cull: none`, `depth_write: false`. ## Properties - `origin_x: 0` and `origin_z: 42`: world x and z the shader measures positions from. 42 is the `Z0` constant `waterfall/wf_water.procGraph` places the waterfall at. - `impact_x: 0` and `impact_z: 60`: the point, relative to the origin, that the churn is centred on and the foam flows away from. The river grid spans z 0.4 to 13.4 relative to the origin, so this point lies upstream of it, and the foam flow moves toward the lip. - `churn_radius: 3`: size of the churned zone around that point, as the falloff `exp(-(d / churn_radius)^2)`. - `foam: 0.55`: blend weight of the foam over the water colour (default 1.0).
▲ 0↑ born
◐
material · born here
❒asset
# wf_sheet_back Waterfall curtain material, the back one of the three staggered curtains of the falls. `waterfall/wf_water.procGraph` builds the still and falling water of the waterfall and assigns this material to one of its parts by name; the graph's header states that the water materials are `.material` assets so the Model receives their blend, cull and depth-write state. The `WaterfallWater` Generator entity in the Procgen Effects Showcase world's `fx_falls` scene runs that graph. The graph builds each curtain from a 6.8 x 21.5 m grid of 44 x 220 cells stood upright with its top at the lip, and assigns this material to `curtain_back`; the graph's comment states that the vertex shader places the real curtain and the grid only carries bounds for culling. Shader: `wf_sheet` (`waterfall/shaders/wf_sheet.shader`). Its README: a waterfall curtain with a ballistic vertex path off the lip, packet-timed ribbon noise that tears with distance fallen, aeration to white, backlit scatter and a refracted background. From its header: the vertex stage places every vertex on the path water takes off a lip, leaving with `out_speed` and falling under gravity (9.81), so the curtain bows out and widens; the fragment pattern is pinned to packets of water, so its streaks stretch as the water speeds up and the sheet tears into ribbons as the breakup threshold rises with the distance fallen. The cliff behind shows through, bent by the ripples. Render state: `blend: alphaBlend`, `cull: none`, `depth_write: false`. ## Properties - `z0: 42`: z of the lip line the water leaves from (the graph's `Z0`). - `base_y: 21.9`: height of the lip, the top edge of the sheet. - `height: 21.5`: drop from the lip to the plunge. - `width: 9.8`: width of the sheet at the lip (default 6.6). - `out_speed: 1.45`: horizontal speed the water leaves the lip with; the sheet moves `out_speed` times the fall time away from `z0` toward -z (default 1.7). - `spread: 0.2`: extra width at the bottom, as width x (1 + spread x s) with s running from 0 at the lip to 1 at the plunge (default 0.22). - `seed: 11`: seed for the sway and the noise patterns (default 3). - `density: 1.1`: multiplier on the sheet's body coverage (default 1.15). - `z_bias: -0.32`: z offset subtracted from the whole sheet (default 0); -0.32 shifts this curtain 0.32 m toward +z, behind the main one.
▲ 0↑ born
◐
material · born here
❒asset
# wf_sheet_front Waterfall curtain material, the front one of the three staggered curtains of the falls. `waterfall/wf_water.procGraph` builds the still and falling water of the waterfall and assigns this material to one of its parts by name; the graph's header states that the water materials are `.material` assets so the Model receives their blend, cull and depth-write state. The `WaterfallWater` Generator entity in the Procgen Effects Showcase world's `fx_falls` scene runs that graph. The graph builds each curtain from a 6.8 x 21.5 m grid of 44 x 220 cells stood upright with its top at the lip, and assigns this material to `curtain_front`; the graph's comment states that the vertex shader places the real curtain and the grid only carries bounds for culling. Shader: `wf_sheet` (`waterfall/shaders/wf_sheet.shader`). Its README: a waterfall curtain with a ballistic vertex path off the lip, packet-timed ribbon noise that tears with distance fallen, aeration to white, backlit scatter and a refracted background. From its header: the vertex stage places every vertex on the path water takes off a lip, leaving with `out_speed` and falling under gravity (9.81), so the curtain bows out and widens; the fragment pattern is pinned to packets of water, so its streaks stretch as the water speeds up and the sheet tears into ribbons as the breakup threshold rises with the distance fallen. The cliff behind shows through, bent by the ripples. Render state: `blend: alphaBlend`, `cull: none`, `depth_write: false`. ## Properties - `z0: 42`: z of the lip line the water leaves from (the graph's `Z0`). - `base_y: 21.9`: height of the lip, the top edge of the sheet. - `height: 21.5`: drop from the lip to the plunge. - `width: 7.6`: width of the sheet at the lip (default 6.6). - `out_speed: 1.95`: horizontal speed the water leaves the lip with; the sheet moves `out_speed` times the fall time away from `z0` toward -z (default 1.7). - `spread: 0.26`: extra width at the bottom, as width x (1 + spread x s) with s running from 0 at the lip to 1 at the plunge (default 0.22). - `seed: 27`: seed for the sway and the noise patterns (default 3). - `density: 0.8`: multiplier on the sheet's body coverage (default 1.15). - `z_bias: 0.34`: z offset subtracted from the whole sheet (default 0); 0.34 shifts this curtain 0.34 m toward -z, in front of the main one.
▲ 0↑ born
◐
material · born here
❒asset
# wf_sheet_main Waterfall curtain material, the middle of the three staggered curtains of the falls. `waterfall/wf_water.procGraph` builds the still and falling water of the waterfall and assigns this material to one of its parts by name; the graph's header states that the water materials are `.material` assets so the Model receives their blend, cull and depth-write state. The `WaterfallWater` Generator entity in the Procgen Effects Showcase world's `fx_falls` scene runs that graph. The graph builds each curtain from a 6.8 x 21.5 m grid of 44 x 220 cells stood upright with its top at the lip, and assigns this material to `curtain_main`; the graph's comment states that the vertex shader places the real curtain and the grid only carries bounds for culling. Shader: `wf_sheet` (`waterfall/shaders/wf_sheet.shader`). Its README: a waterfall curtain with a ballistic vertex path off the lip, packet-timed ribbon noise that tears with distance fallen, aeration to white, backlit scatter and a refracted background. From its header: the vertex stage places every vertex on the path water takes off a lip, leaving with `out_speed` and falling under gravity (9.81), so the curtain bows out and widens; the fragment pattern is pinned to packets of water, so its streaks stretch as the water speeds up and the sheet tears into ribbons as the breakup threshold rises with the distance fallen. The cliff behind shows through, bent by the ripples. Render state: `blend: alphaBlend`, `cull: none`, `depth_write: false`. ## Properties - `z0: 42`: z of the lip line the water leaves from (the graph's `Z0`). - `base_y: 21.9`: height of the lip, the top edge of the sheet. - `height: 21.5`: drop from the lip to the plunge. - `width: 9.2`: width of the sheet at the lip (default 6.6). - `out_speed: 1.7`: horizontal speed the water leaves the lip with; the sheet moves `out_speed` times the fall time away from `z0` toward -z (default 1.7). - `spread: 0.22`: extra width at the bottom, as width x (1 + spread x s) with s running from 0 at the lip to 1 at the plunge (default 0.22). - `seed: 3`: seed for the sway and the noise patterns (default 3). - `density: 1.15`: multiplier on the sheet's body coverage (default 1.15). - `z_bias: 0`: z offset subtracted from the whole sheet (default 0); the middle curtain sits at the unshifted position.
▲ 0↑ born
✦
shader · born here
❒asset
# wf_particle Waterfall particle card: mist, foam and droplet looks selected by `mode`, with sun forward-scatter and a view-dependent rainbow, premultiplied output and a soft depth fade. One shader draws the whole spray family: - Mode 0, mist: big soft camera-facing cards (`zero_billboard`). A four-octave `fx_noise` fBm, offset per particle and drifting with time, billows a round puff. It is lit by the ambient light and by the sun through a Henyey-Greenstein phase (g 0.62), so the mist glows when the sun is behind it. The rainbow lives in these cards: a band 42 degrees from the anti-solar point, about 1.7 degrees half-width, red outside and violet inside, scaled by `rainbow`. - Mode 1, foam: bright bubbly clumps on camera-facing cards. Worley cells drift through a ragged disc, lit by ambient and sun light. - Mode 2, droplet: a teardrop on a card turned onto its motion (`zero_billboard_streak`), with a fat head leading along +Y and a tail thinning to a hair, plus a sun glint on the head when the sun is behind it. - Mode 3, flat foam: the foam look on a card lying on the water, its right along world X and its up along world Z (`zero_card_clip`). Every card dissolves into whatever is drawn behind it over `depth_fade` (`zero_scene_depth_fade`), so cards blend softly where they meet rock or water. The output is premultiplied: the colour, scaled by `energy`, carries its own coverage, and the rainbow and glint add on top. Three graphs beside it in `waterfall/` draw with it, all premultiplied with culling off and depth writes off, and in the Procgen Effects Showcase world the `fx_falls` scene places them: `wf_mist` (mode 0, `opacity` from its `density` input, default 0.7, `energy` 1.7, `depth_fade` 2.2, `rainbow` from its `rainbow` input, default 1.0), `wf_foam` (mode 1, `depth_fade` 0.9, `rainbow` 0) and `wf_spray` (mode 2, `depth_fade` 0.6, `rainbow` 0). Each writes `data0` from a colour ramp over life and `data1` as (particle id, life, 0). The shader includes `@builtin::shaderModules.billboard`, `fx_noise` and `zero::scene_depth`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `mode` | float | 0 | Look selector, range 0 to 3: mist, foam, droplet, flat foam. | | `opacity` | float | 1 | Multiplies the coverage (range 0 to 4). | | `energy` | float | 1 | Multiplies the lit colour (range 0 to 8). | | `depth_fade` | float | 1.2 | Distance over which a card fades into the surface behind it (range 0 to 10). | | `rainbow` | float | 0.6 | Strength of the rainbow in mist cards (range 0 to 4). | | `vertexBoundsDilation` | float | 11 | 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` | Colour, multiplied by the lighting. | | `data0.a` | Opacity over life. | | `data1.x` | Particle id; its low 16 bits seed the per-card noise offsets. | | `data1.y` | Life, 0 to 1. | | `data1.z` | Spin phase, as the shader header names it; the graphs write 0. |
▲ 0↑ born
✦
shader · born here
❒asset
# wf_pool Plunge-pool water: travelling ripples, churn turbulence that grows toward the impact, a two-phase radial foam flow, depth-driven shore and rock foam, a fresnel sky reflection and sun glitter. All positions are taken relative to the waterfall origin (`origin_x`, `origin_z`) on the world XZ plane. The surface normal sums four travelling sine waves, rings running outward from the impact point, and an `fx_noise` fBm chop whose strength rises with the churn, a Gaussian falloff of distance from the impact over `churn_radius`. The water colour comes from the depth already drawn underneath (`zero_scene_depth_fade`): light teal where the bed is close, dark blue-green where it is deep. Over that it mixes a sky gradient from a horizon `(0.62, 0.76, 0.92)` to a zenith `(0.18, 0.34, 0.66)` by a Schlick fresnel term, and adds two lobes of sun glitter, stronger in the churn. Foam is drawn from two flow phases advected outward from the impact and cross-faded so the cycle loops smoothly, plus the churn itself, a spread term around the impact, ragged contact foam where the water meets rock or shore (a depth fade over 0.42), fine breakup noise and worley lace cells. The foam colour is a lit white, mixed in by `foam`. The alpha runs from 0.55 at the shore to 1 in deep water, raised by the foam. Two materials use it, both alpha-blended with culling off and depth writes off, and the `wf_water` graph (`waterfall/wf_water.procGraph`) draws both in the Procgen Effects Showcase world's `fx_falls` scene: `wf_pool_mat` on the 21 by 18.5 plunge pool (origin z 42, impact at (0, -3.5), `churn_radius` 3.7, `foam` 1), and `wf_river_mat` on the 7.2 by 13 river above the lip (origin z 42, impact at (0, 60), `churn_radius` 3, `foam` 0.55). The shader includes `fx_noise` and `zero::scene_depth`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `origin_x` | float | 0 | World X of the waterfall origin; positions are measured from it. | | `origin_z` | float | 0 | World Z of the waterfall origin. | | `impact_x` | float | 0 | X of the plunge point, relative to the origin. | | `impact_z` | float | -3.4 | Z of the plunge point, relative to the origin. | | `churn_radius` | float | 3.6 | Radius of the churned water around the plunge point (range 0.5 to 20). | | `foam` | float | 1.0 | How strongly the foam is mixed over the water (range 0 to 2). |
▲ 0↑ born
✦
shader · born here
❒asset
# wf_rock World-space procedural wet rock: strata, moss, mineral streaks, bump and spray-driven wetness for the meshed signed-distance cliff of the waterfall. Every pattern is computed from the world position relative to the waterfall's origin (`origin_x`, `origin_y`, `origin_z`). It is a `surface()` shader that fills a `PbrSurface`. A height field of `fx_noise` fBm plus ridged fBm gives the bump normal, scaled by `bump`. The dry rock is warm and pale, banded into long warped horizontal beds with grain. Dark seeps run down the face on either side of the falls, fading out between 6 and 17 units from its centre line. Wetness comes from the falls' spray around the plunge line, the waterline around the pool, and the seeps; wet rock is darker (by up to 42 percent) and glossier (roughness from 0.92 down to 0.28). Moss grows on gentle upward faces that stay wet, scaled by `moss`, and rust-brown mineral streaks run down the face. The albedo is multiplied by `gain` and `tint`, and occlusion follows the height field. The `wf_env` graph (`waterfall/wf_env.procGraph`) applies it to the cliff, plunge basin and boulders it contours from signed-distance solids, with the origin at z 42, `bump` 0.55 and `moss` 1.0. The Procgen Effects Showcase world's `wf_ground_mat` material uses it with the same origin, `bump` 0.4, `gain` 1.15, `moss` 1.3 and a warm `tint` (1.25, 1.08, 0.85), and the Procgen Effects Showcase world's `fx_falls` scene places that material. The shader includes `fx_noise` and `@builtin::shaderModules.pbr_shading`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `bump` | float | 0.55 | Strength of the bump normal (range 0 to 3). | | `moss` | float | 1.0 | Amount of moss on wet upward faces (range 0 to 2). | | `tint` | color | [1, 1, 1, 1] | Multiplies the albedo. | | `gain` | float | 0.75 | Multiplies the albedo (range 0 to 2). | | `origin_x` | float | 0 | World X of the waterfall origin. | | `origin_y` | float | 0 | World Y of the waterfall origin. | | `origin_z` | float | 0 | World Z of the waterfall origin. |
▲ 0↑ born
✦
shader · born here
❒asset
# wf_sheet Waterfall curtain: a ballistic vertex path off the lip, packet-timed ribbon noise that tears with distance fallen, aeration to white, backlit scatter and a refracted background. The vertex stage reads each vertex's place on the sheet back from the grid's own position: `u` across a 6.8-wide grid and `s` from 0 at the lip (`base_y`) to 1 at the bottom of `height`. It then places the vertex on the path water takes off a lip: it leaves with `out_speed` and falls under gravity (9.81), so after falling a distance `s * height` it has moved `out_speed * t` outward along -Z from `z0`. The sheet widens by `spread` toward the bottom, sways a little more the farther it has fallen, and is pushed along -Z by `z_bias`. The fragment pins its pattern to packets of water: a packet released at time `t0` has fallen `0.5 * g * (t - t0)^2`, so the noise is sampled at the time each point's water left the lip. As the water speeds up its streaks stretch, and the sheet tears into ribbons because the breakup threshold rises with the distance fallen. Broad tongues, fine strands and grain come from `fx_noise` seeded by `seed`. Aeration turns the water from a deep green-blue to white where the flow is thin and fast, crests catch the sun through a Henyey-Greenstein phase (g 0.55), and the cliff behind shows through, bent by the ripples (`zero_scene_color_refract`). The tail fades into the plunge over the last 7 percent and the top edge fades in at the lip. Three materials use it, all alpha-blended with culling off and depth writes off, and the `wf_water` graph (`waterfall/wf_water.procGraph`) hangs one curtain from each on a 6.8 by 21.5 grid in the Procgen Effects Showcase world's `fx_falls` scene: | Material | `width` | `out_speed` | `spread` | `seed` | `density` | `z_bias` | |---|---|---|---|---|---|---| | `wf_sheet_back` | 9.8 | 1.45 | 0.2 | 11 | 1.1 | -0.32 | | `wf_sheet_main` | 9.2 | 1.7 | 0.22 | 3 | 1.15 | 0 | | `wf_sheet_front` | 7.6 | 1.95 | 0.26 | 27 | 0.8 | 0.34 | All three use `z0` 42, `base_y` 21.9 and `height` 21.5. The shader includes `fx_noise`, `zero::scene_depth` and `zero::scene_color`. ## Properties | Property | Type | Default | Meaning | |---|---|---|---| | `width` | float | 6.6 | Width of the curtain at the lip (range 0.5 to 40). | | `height` | float | 21.5 | Height the water falls (range 1 to 80). | | `z0` | float | 0 | World Z of the lip (range -1000 to 1000). | | `base_y` | float | 21.9 | World height of the lip (range -10 to 100). | | `out_speed` | float | 1.7 | Speed at which the water leaves the lip along -Z (range 0 to 8). | | `spread` | float | 0.22 | How much wider the curtain is at the bottom, as a fraction of `width` (range 0 to 1). | | `seed` | float | 3 | Seed for the curtain's noise and sway (range 0 to 99). | | `density` | float | 1.15 | Multiplies the sheet's body before it becomes alpha (range 0 to 3). | | `z_bias` | float | 0.0 | Shift of the whole curtain along -Z (range -3 to 3); the three curtain materials use -0.32, 0 and 0.34. | | `vertexBoundsDilation` | float | 3.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. |
▲ 0↑ born
·
procgraph · born here
❒asset
# wf_env The rock of the waterfall scene: the cliff, the plunge basin and the boulders, as signed-distance solids contoured to one mesh. The cliff face is the z = 0 plane facing -z, the river runs along +z on top of the plateau and spills over the lip at (0, 21.9, 0), the ground is at y = 0 and the pool surface at y = -0.35. The cliff and boulders carry deep fluted noise; the ground slab with the basin cut into it carries only a little, so the pool bed stays smooth and the shore reads as a beach. The mesh draws with the `wf_rock` shader. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wf_env", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, params = { resolution = 150 } }) ``` | Input | Default | What it does | |---|---|---| | `resolution` | 150 | Cells along the contoured volume's longest side (40 to 260): more is finer rock and a longer cook. | | `roughness` | 1 | How deep the noise cuts into the cliff and boulders (0 to 3). | | `seed` | 7 | Re-rolls the noise. | The output `env` is the one mesh. It belongs with `wf_water`, `wf_spray`, `wf_foam` and `wf_mist`, which share its frame.
▲ 0↑ born
·
procgraph · born here
❒asset
# wf_foam The white boil where the waterfall lands: churning clumps of foam that heave up out of the plunge, roll outward across the pool and burst. They are bubbly cards (the `wf_particle` shader in its foam mode) born on a ring around the impact point at (0, -0.3, -3.5) and driven by a vortex around it, in the frame `wf_env` sets up. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wf_foam", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` The output `foam` is the cards. The timeline has no end and plays at 30 fps.
▲ 0↑ born
·
procgraph · born here
❒asset
# wf_mist The waterfall's mist: big soft cards born at the plunge and along the falling face, carried outward across the pool on a gentle breeze and curl turbulence. The `wf_particle` shader draws a rainbow inside these cards from the angle between the view ray and the point opposite the sun, so the bow appears where it would in the real spray. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wf_mist", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` | Input | Default | What it does | |---|---|---| | `rainbow` | 1 | Strength of the rainbow drawn in the mist (0 to 4). | | `density` | 0.7 | How thick the mist stands (0 to 3). | The output `mist` is the cards. The timeline has no end and plays at 30 fps.
▲ 0↑ born
·
procgraph · born here
❒asset
# wf_spray The waterfall's droplets: beads torn off the lip that streak down beside the falling curtain, the plume thrown up where it lands, and the smaller drops those throw when they strike water and rock, all one GPU solver family drawn with the `wf_particle` shader. It shares `wf_env`'s frame: the lip runs along x at y = 21.9. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wf_spray", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` The output `spray` is every droplet. The timeline has no end and plays at 30 fps.
▲ 0↑ born
·
procgraph · born here
❒asset
# wf_water The waterfall's water: three staggered falling curtains, the plunge pool and the river above the lip. The curtains draw with the `wf_sheet_*` materials, whose vertex shader shapes the falling sheet; the pool and river draw with `wf_pool_mat` and `wf_river_mat`. Its parts stand at z = 42 in the generator's own space, and the materials state that spot too (`z0`, `origin_z`). ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("wf_water", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` The output `water` is one entity output holding every part. The timeline has no end and plays at 30 fps, which keeps the water's materials moving.
▲ 0↑ born
·
assettype · pulled in
❒asset
# Package (asset type) A package is an asset — a `<Name>.package/` folder that bundles components, modules, scenes, presets, tools, and any other typed sub-assets under one identity, installed into a world as one unit. Packages are how authoring sets get distributed across worlds. A **library** is the addressable root scope content resolves under (`@builtin`, `@<name>`) — a whole world mounted into this one under a namespace, via `zeromind.installLib` / `world.installLibrary`. A package is an asset that lives inside such a root, and one library holds as many packages as its author put there. A package is installed by guid the way every asset is (`zeromind.install`, `zeromind.installAsset`). ## When to use one - You're authoring a coherent feature suite (character controller stack, voxel engine, UI kit, animation library) and want to ship it as one install target. - You want a stable identity worlds can install and resolve sub-assets against (`@<lib>::pkg.sub_module`). - You want versioning + a per-package metadata layer that travels with the contents. If you're authoring inside a single world and don't need a separate install lifecycle, you don't need a package — drop your `.component` / `.module` / etc. directly in `/zero/source/`. Packages are for cross-world distribution. ## Where it lives - Source: `/zero/source/.../<Name>.package/` (or, for legacy packages, a folder containing `package.yaml` at its root). - Identity: `<Name>` (the `.package` suffix collapses in identity — mirrors `.module`). A file at `<Name>.package/<sub>/init.luau` resolves under the same identity it would at `<Name>/<sub>/init.luau`. - Folder shape (container-style — open child set): - `package.yaml` — metadata (name, version, description). **Required.** - `README.md` — instance documentation. **Required.** - `.metadata` — agent-editable tags + free-form fields. **Required.** - Sub-asset folders: any combination of `.component/`, `.module/`, `.scene/`, `.preset/`, `.tool/`, `.toolbox/`, `.material/`, `.shader/`, etc. The validator permits unlisted children (`allow_unlisted: true`) by design — packages are open containers. ## How to create one ```luau asset.create("package", "<Name>") -- Creates: /zero/source/<Name>.package/ -- package.yaml (metadata scaffold) -- README.md (instance README template) -- `folder` places it in a subfolder of /source instead of the root: asset.create("package", "<Name>", { folder = "systems" }) ``` Then scaffold sub-assets inside it: ```luau local pkg = asset.resolve("<Name>.package") asset.create("component", "Spinner", { into = pkg }) asset.create("module", "util", { into = pkg }) ``` ## How it operates 1. **Registration.** Writing `package.yaml` indexes the package with the package registry. 2. **Install.** A package is installed by guid, the way every asset is: `zeromind.install` from the shared library, or `tools.use("zeromind", "installAsset", <guid>)` inside the engine. The install writes the package's files (and the deps its `.refs` record) into this world's source, so its sub-assets resolve here. `tools.use("zeromind", "preview", <guid>)` reports what an install would write before it writes anything. 3. **Sub-asset resolution.** Because `.package` collapses in identity, sub-asset paths work whether the package folder is suffixed (`<Name>.package/<sub>`) or not (`<Name>/<sub>`). 4. **Updates.** `tools.use("zeromind", "updates")` lists installed content with upstream changes available; re-running the install pulls them. 5. **Metadata.** `package.yaml::name` overrides the folder stem if present (rare); `version` + `description` are surfaced in the package index. 6. **Hot reload.** Edits to sub-assets hot-reload as normal; edits to `package.yaml` reload package metadata. ## Discovery - `asset.list("package")` — every registered package. - `asset.inspect("<name>")` — sub-asset catalog, source, this type README. - `ls /zero/source/<Name>.package` lists the files the folder holds. - `library.list()` — the library assets registered in this world, including the ones packages under an installed library contribute. ## Authoring conventions - Name packages by their feature (`voxels`, `cameraRigs`, `dialogSystem`), not by their owner — the host library is the `@<lib>::` scope prefix. - Cluster cohesive sub-assets together. A "character controller" package should ship the controller component, its preset configs, its supporting modules, and a demo scene — not just the component. - Document the package's surface in `README.md` — what install installs, what each sub-asset does, how they relate. Agents reading `cat /zero/source/<Name>.package/README.md` get the full picture in one shot. - Version conservatively — breaking a package means breaking every world that installed it. Use semantic version bumps. ## Common pitfalls - **Missing `package.yaml`.** Without it the folder isn't recognized as a package even if it has a `.package/` suffix. - **Dependency installs.** A package that depends on another package must declare it (in `package.yaml::dependencies` once supported) and the parent world must install dependencies in order. - **Identity collapse.** Sub-asset paths skip the `.package` suffix. Don't include `.package` in `require` strings. ## Referencing inside a package: the `~` rule `~` means **this package**, resolved structurally from the referring file's own location. It is the only package-specific syntax. It is rename-safe (no package name is ever written) and library-agnostic (it never names the host library, so it survives `@builtin` being renamed or the package being mounted elsewhere). `~.tail` maps to `<pkg>.package/tail` from anywhere inside the package. | Referencing from | Use | Example | |---|---|---| | An asset/module **inside this package** | `~.tail` | `require("~.modules.myThing")`, `shader: "~.shaders.myThingBlend"` | | A **different package** under the same root | root-relative identity | `require("@root::systems.otherPkg.modules.x")` | | A **different library's** public API (a deliberate external dependency) | `@otherlib::…` | `require("@physics::modules.rigidbody")` | **Never write `@builtin::` (or any host-library name) to reference your own package** — that couples the package to the library it currently lives in and breaks if the library is renamed or the files move. Use `~.`. It works from Luau `require()` and from asset-reference strings in data files (a material's `mat.yaml` `shader:` field, a component's default asset ref); the engine resolves it against the referring file's own package. `asset.resolve` takes a `~.` name the same way, against the package of the file that calls it: `asset.resolve("~.materials.myThingStandard", "material")`. `~.` is the package-relative self-reference; `@root::` is the root-relative one (the library root, or the world source tree for non-library content). The `core/requiring-modules` guide covers the root model in full. A package that ships substantial functionality should include a `.guide` asset (a `<name>.guide/guide.md` folder anywhere under the package); the `guides` tool discovers it live, so collaborators find the system the way they find built-in guides. A package's test suite reaches the shared `Test` framework through its enclosing asset: `local Test = asset.containing(__FILE__).modules.shared` (`asset.containing` returns the deepest enclosing typed asset, the `.testSuite`, not the outer `.package`). ## Related types - Any of `.component`, `.module`, `.scene`, `.preset`, `.tool`, `.toolbox`, `.material`, `.shader`, `.style`, `.service`, `.importer` — packages bundle these. ## In the Inspector Package: the name, version and description package.yaml declares, how many things the package holds and what they are, and **Open** for package.yaml. A package.yaml that does not decode is listed under Problems with the decoder's error.
▲ 0↓ import
backing path · effectShowcase.package

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.