# 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.
# 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.
# 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.
# effectShowcase
The procedural effects of the Procgen Effects Showcase world. Each one is a `.procGraph` that plays
through a `Generator`, and every shader, material and module a graph draws with sits beside it in
this package, so the package carries everything its graphs need. Each graph's README says what it
makes, how to place it and what each of its inputs changes.
## Contents
| Folder | Graphs | What they make |
|---|---|---|
| `combat/` | `impact`, `muzzleFlash`, `tracer` | A round striking a hard surface, the bloom at a barrel as a weapon fires, and the glowing streak of a round in flight. They draw with `fxFlash`, `fxSmoke` and `fxSpark` in `combat/shaders/`. |
| `blast/` | `wall_blast` | A charge blowing a breach through a stone block wall, on a 9.6 s loop. |
| `storm/` | `storm`, `tower` | A thunderstorm around a lone tower: wind-driven rain, lightning striking on the schedule `schedule.module` keeps, and sparks and smoke where strikes land. `tower` is the stone keep it stands around. |
| `rift/` | `arcane_rift` | A rift tearing open in the ground, its motes and rubble moved by the compute shaders in `rift/compute/`. |
| `dragon/` | `dragon_breath` | A dragon's fire breath sweeping a courtyard: a flame jet, rolling smoke and drifting embers. |
| `launch/` | `launch` | A heavy-lift rocket liftoff on one looping timeline, with the heat-haze material `rk_haze_mat`. |
| `waterfall/` | `wf_env`, `wf_water`, `wf_spray`, `wf_foam`, `wf_mist` | A waterfall built in parts: the cliff, basin and boulders, the falling and still water, the droplets, the foam where the falls land, and the mist with its rainbow. Its water materials are in `waterfall/materials/`. |
| `shaders/` | | `fx_noise`, the noise functions the waterfall and wall blast shaders include. |
## Playing one
A graph plays on a `Generator` component bound to it:
```lua
-- `graph` is the graph's reference: the AssetRef `asset.resolve` or a search returns for it.
local e = entity.spawn("impact", { position = { 0, 1, 0 } })
e.component.add("Generator", { graph = graph, playOn = "load" })
```
Set a graph's inputs with the Generator's `params`, e.g. `params = { size = 3 }`.