// undine docs
Streamflow
Streamflow is what makes Undine feel real-time. As substeps complete on the GPU, particle frames stream into Blender's playback without ever being copied back to the host until you actually need them.
It is not a 'preview render' grafted on top of a bake. The solver and the viewport share one cache, and the runtime contract guarantees that the preset you see in the panel is the preset that ran.
Streamflow modes
The Actions tab exposes a Streamflow End-Mode selector. Two modes are visible to the user; both run the full solver, the difference is what gets meshed live.
| Mode | What runs live | When to use |
|---|---|---|
| Streamflow Points | Cheap point cloud streamed to viewport per frame. | Iteration speed comes first. Use while finding timing, scale, emission rate, gross motion. |
| Mesh Every Frame | Lockstep meshing per frame using the Meshify-tab preset (live_high, final_hero, final_ultra, …). | When the look matters — surface tension, sheet thickness, anisotropy — and you want to judge the rendered mesh, not the points. |
How a frame flows
The diagram shows the lifecycle of a single Streamflow frame. The solver writes expensive points into the shared cache, the meshifier reads them, the addon publishes the result to the viewport — all without leaving the device for the simulation portion.
Solver, meshifier, and viewport coordinate through one cache. Cancel is honored at any boundary.
graph LR
Sub["Substep loop (GPU)"]
Pts["Cache: expensive points"]
Mesh["meshify_tool.exe"]
Ply["PLY / Alembic"]
View["Blender viewport"]
Sub --> Pts
Pts --> Mesh
Mesh --> Ply
Ply --> View
Sub --> View
Runtime contract
Before any frame is dispatched, the addon resolves a runtime contract: end-mode, preset, profile, input policy, world version. The contract is asserted by the solver before it runs.
The contract is what guarantees that selecting a final preset in the Meshify tab actually applies a final preset — not a silent fallback to whatever the global preference happened to be. If the assertion fails, the run aborts cleanly with a diagnostic instead of producing a misleading result.
| Contract field | Meaning | Example |
|---|---|---|
| end_mode | What kind of output the run produces. | STOP · STREAMFLOW · MESH_PREVIEW · MESH_FINAL |
| preset | The Meshify quality bucket. | live_fast · live_high · final_hero · final_ultra |
| profile | The solver-side resolved profile. | live_fast · final_hero · final_ultra |
| input_policy | What the meshifier consumes. | expensive_points_only · cheap_points_or_expensive |
| runtime_world | Cache-versioning identifier. | runtime_new (production paths) |
| tool_required | Whether meshify_tool.exe must run. | true for production presets |
Whitewater FX (Beta)
Whitewater FX is separate from the main solver in the beta. It produces spray, foam, and bubbles as a one-way, disposable visual layer; it does not participate in P2G, pressure, G2P, viscosity, or primary Meshify.
The primary FLIP/APIC particles remain the only real water mass. Secondary whitewater particles are generated from the approved water behavior and do not return forces, volume, pressure changes, or surface blobs to the main simulation.
| Kind | Visual role | Motion model |
|---|---|---|
| Spray | Airborne droplets from impacts, jets, waterfalls, and fast wakes. | Moves with inertia, falls under gravity, and dissipates by lifetime. |
| Foam | Surface foam that floats or accumulates on wakes, turbulent borders, and impacts. | Partially follows local fluid velocity to read as drag over the water sheet. |
| Bubbles | Subsurface or near-surface aeration in energetic water. | Rises through buoyancy and uses a light cyan read for viewport separation. |
| Whitewater | The global term for the mixture of aerated water, foam, spray, and bubbles. | Appears where the fluid gains visual energy. |
Secondary payload and viewport display
For viewport preview, Whitewater uses a realtime path parallel to Streamflow. It reads primary particles from GPU memory when available, stays compatible with the resident pipeline, and applies emission and transfer budgets before publishing anything to Blender.
SNP5 / wire v6 receives secondary payloads only when the payload is ready. If preview cost exceeds the budget, the path degrades by decimation or frame skip instead of blocking the main solve.
The viewport exposes independent toggles for fluid, spray, foam, and bubbles, so the artist can show or hide each layer without restarting the simulation and without changing the physics.
Secondary cache and Meshify isolation
For final quality, Whitewater has a Production Bake path after an approved particle or Streamflow cache. It writes its own versioned secondary cache at <run>/whitewater/frame_XXXXXX.gpfb, distinct from the primary <run>/particles/ cache.
The whitewater cache stores render-ready attributes such as position, velocity, radius, age, lifetime, kind, and id, so Blender can render the layer through Geometry Nodes or instancing.
Meshify is shielded to consume only the primary water cache. The whitewater/ folder, Undine_Whitewater_* objects, and secondary kind attribute are not valid primary mesh inputs, so the main liquid surface stays separate from foam, spray, and bubbles.
SNAP playback
SNAP is the viewport-update preset attached to Streamflow. It controls how aggressively Blender's playback tries to keep up with the solver as frames arrive.
Realtime Every Sim Frame attempts to display every frame the solver produces; less aggressive presets sample frames to keep the UI fluid when the solver outpaces refresh rate.
Cancel, store, replay
A Streamflow run is interruptible. Cancel stops the solver at the next safe boundary; cached frames remain valid. Store accepts a meshed result; Discard rejects it without touching the simulation cache.
This is a subtle but important property: cancelling a preview never costs you the simulation. The expensive part — the particles — stays on disk.