Real-time GPU particle field generator inspired by Refik Anadol's fluid data sculptures. Drives 500K+ particles through a full 3D Navier-Stokes velocity field on the GPU, sharing the output with TouchDesigner via Syphon (macOS) or Spout (Windows) for live visuals.
FieldGen runs an 11-stage fluid simulation entirely on the GPU using Vulkan compute shaders:
- Inject — emits density and temperature into the field from a configurable source
- Forces — buoyancy, vortex confinement, cohesion, point/sphere/line/plane attractors, gravity
- Advect — semi-Lagrangian advection moves the field through itself
- Diffuse — Jacobi iteration for viscous diffusion
- Pressure solve — divergence → pressure (Jacobi) → gradient subtraction for incompressibility
- Boundary — clamps velocities and densities at domain edges
- Derived fields — computes vorticity/curl magnitude for coloring
- Particle advection — RK4 integration of 500K particles through the velocity field with gravity, emitter shapes, and attractor physics
The particle positions are packed into an RGBA texture and published over Syphon/Spout so TouchDesigner (or any Syphon/Spout client) can render them as geometry in real time.
Every parameter is controllable live via OSC on port 9000 — connect any OSC source (TouchDesigner CHOPs, iPad apps, Max/MSP, etc.) and all values are 0-1 with automatic internal remapping.
- Vulkan compute — all simulation runs on GPU compute shaders, zero CPU bottleneck
- 500K particles with RK4 integration, gravity, and initial velocity on spawn
- 48x48x48 Navier-Stokes solver — full incompressible fluid with pressure projection
- 4 emitter shapes — volume, point, sphere surface, disc (for water/splash effects)
- 4 attractor shapes — point, sphere, vertical line, horizontal plane
- Syphon/Spout texture sharing to TouchDesigner, VDMX, Resolume, etc.
- OSC control — 40+ parameters, all accepting 0-1 from TouchDesigner
- Dear ImGui overlay — live diagnostics, system health, CFL monitoring, parameter readout
- OpenGL preview — built-in particle rendering with additive blending
- Vulkan SDK 1.3+ — download here
- macOS: uses MoltenVK (included in Vulkan SDK)
- Windows: native Vulkan drivers
- CMake 3.20+
- C++20 compiler (Clang 14+, GCC 12+, MSVC 2022+)
- Git (for cloning dependencies)
- Xcode Command Line Tools (macOS only, for building Syphon)
git clone https://github.com/pkmiecinski/FieldGen.git
cd FieldGen
./setup.shThe setup script will:
- Check for Vulkan SDK, CMake, and glslc
- Clone dependencies (GLFW, GLM, oscpack, Dear ImGui, Syphon/Spout)
- Build Syphon framework (macOS) or set up Spout (Windows)
- Run CMake and build the project
Then run:
cd build
./fieldgenIf you prefer to build manually:
# Clone dependencies
git clone --depth 1 --branch 3.4 https://github.com/glfw/glfw.git external/glfw
git clone --depth 1 --branch 1.0.1 https://github.com/g-truc/glm.git external/glm
git clone --depth 1 https://github.com/RossBencina/oscpack.git external/oscpack
# Build
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
./fieldgenFieldGen publishes particle positions as an RGBA32F texture over Syphon (macOS) or Spout (Windows).
- Add a Syphon Spout In TOP — select "FieldGen_Particles"
- Add a TOP to SOP — this converts pixel colors to point positions
- Important: positions are encoded as 0-1 in the texture. Remap back to world space:
- Add a Math TOP between Syphon In and TOP to SOP: set Range1 =
0, 1and Range2 =-1, 1 - Or in a GLSL TOP:
vec3 pos = texture(...).rgb * 2.0 - 1.0
- Add a Math TOP between Syphon In and TOP to SOP: set Range1 =
- Render the SOP with a Geometry COMP and point sprites
All parameters accept 0 to 1. Add an OSC Out CHOP pointing to localhost:9000:
| OSC address | What it controls |
|---|---|
/fieldgen/inject/density |
Fluid density emission |
/fieldgen/inject/temperature |
Temperature emission (drives buoyancy) |
/fieldgen/inject/radius |
Emitter radius |
/fieldgen/inject/x, y, z |
Emitter position |
/fieldgen/forces/buoyancy |
Hot fluid rises |
/fieldgen/forces/vortex |
Vortex confinement (swirl) |
/fieldgen/forces/cohesion |
Particles attract to density |
/fieldgen/forces/entropy |
Random perturbation in old regions |
/fieldgen/attractor/x, y, z |
Attractor position |
/fieldgen/attractor/strength |
Attractor pull force |
/fieldgen/attractor/shape |
0=point, 1=sphere, 2=line, 3=plane |
/fieldgen/attractor/radius |
Sphere attractor size |
/fieldgen/gravity/x, y, z |
Constant gravity (0.5 = zero) |
/fieldgen/emit/shape |
0=volume, 1=point, 2=sphere, 3=disc |
/fieldgen/emit/dir_x, dir_y, dir_z |
Emit direction |
/fieldgen/emit/speed |
Initial particle velocity |
/fieldgen/emit/spread |
0=tight stream, 1=random |
/fieldgen/particles/strength |
Field influence on particles |
/fieldgen/particles/damping |
Velocity damping |
/fieldgen/particles/life |
Life decay rate |
/fieldgen/particles/speed |
Max speed clamp |
/fieldgen/viscosity |
Fluid viscosity |
/fieldgen/diffuse_iters |
Diffuse solver iterations |
/fieldgen/pressure_iters |
Pressure solver iterations |
See MANUAL.md for the full parameter reference with visual descriptions.
The GLFW window shows an ImGui overlay:
- Diagnostics checkbox — shows system health, CFL number, field statistics, particle stats, recent OSC changes
- Preview checkbox — enables built-in OpenGL particle rendering
- Quit button — clean shutdown
- ESC key — also quits
FieldGen/
├── main.cpp # Application entry, OSC bindings, render loop
├── CMakeLists.txt # Build configuration
├── setup.sh # One-step setup & build script
├── shaders/
│ ├── inject_sources.comp # Density/temperature injection
│ ├── apply_forces.comp # Buoyancy, vortex, attractor forces
│ ├── advect_field.comp # Semi-Lagrangian advection
│ ├── diffuse.comp # Jacobi viscous diffusion
│ ├── divergence.comp # Divergence computation
│ ├── pressure_solve.comp # Jacobi pressure solver
│ ├── gradient_subtract.comp # Pressure gradient subtraction
│ ├── boundary.comp # Domain boundary conditions
│ ├── derived_fields.comp # Vorticity / curl magnitude
│ ├── particle_advect_v2.comp # Particle physics (RK4, gravity, emitters)
│ └── init_sdf.comp # Signed distance field init
├── src/
│ ├── core/ # Vulkan engine (device, buffers, pipelines)
│ ├── field/ # Field generator, params, particle structs
│ ├── io/ # OSC controller, Syphon/Spout sharing
│ ├── diagnostics/ # System health, ImGui overlay
│ └── render/ # OpenGL preview renderer
├── TD/ # TouchDesigner example project
├── MANUAL.md # Full parameter manual (plain English)
└── external/ # Dependencies (gitignored, cloned by setup.sh)
MIT