Niagara Ferrofluid SDFS
Adapted version of a ShaderToy ferrofluid study (original shader toy by liuk718), rebuilt in Unreal using Niagara particles as proxy geometry and per-pixel SDF raymarching, so the blobs fuse into one liquid mass while writing real depth like any other mesh.
Overview
The core idea behind the system was to render a true metaball surface without paying for it across the whole screen. Rather than marching every pixel from a fullscreen quad, each blob is a Niagara particle carrying a small proxy sphere, so the rasterizer decides up front which pixels could possibly contain surface and only those trace a ray. Each one solves the smooth-minimum of every blob analytically, letting them fuse into a single liquid mass with stretched necks and stray droplets, while still writing real depth and sorting correctly against the rest of the scene.
The system was built with flexibility in mind. The blob motion, fusion strength, droplet distribution, surface detail and edge softness are all generated procedurally and exposed as parameters, so the look can be finetuned without touching the shader logic.
Niagara Setup / Material TECHNICAL Implementation
Niagara Setup / Material Technical Implementation
The effect runs as a GPU Niagara system where each particle represents one blob. Rather than rendering the particles directly, the mesh renderer draws a small sphere per particle that acts purely as proxy geometry — bounding hardware that tells the rasteriser which pixels could possibly contain surface. Nothing about the visible shape comes from those spheres; they exist so the expensive work never runs on empty space.
The particle update stage positions each blob from a deterministic hash-seeded trajectory, ported from the original ShaderToy. Each particle derives its own frequency, phase, orbit radius and size from its index, then writes:
Position — independent sine and cosine motion per axis
Scale — the proxy sphere, deliberately oversized so the fused surface never clips through its own bounds
Blob radius — the true size used by the surface solve
The material does the actual rendering. For every pixel covered by a proxy, it marches a short ray and evaluates the smooth-minimum of all blobs analytically, recomputing their positions in-shader from the same hash and clock the Niagara module uses. Where no surface is found the pixel is discarded, so the silhouette is the fused isosurface rather than the proxy spheres. A bisection step refines the hit, and the surface normal comes from the field gradient — which conveniently also gives ambient occlusion, since the gradient flattens exactly where blobs merge.
Because the geometry and the surface are solved from the same maths in two different places, they must share one clock. A Blueprint accumulates a single time value each tick and writes it to both the Niagara user parameter and a Material Parameter Collection, guaranteeing the proxies and the rendered surface can never drift apart — including under Movie Render Queue, where engine-side clocks diverge.