- C++ 95.4%
- CMake 4.6%
| .gitignore | ||
| bounds.hpp | ||
| bounds_renderer.cpp | ||
| bounds_renderer.hpp | ||
| CMakeLists.txt | ||
| debug_density_field_renderer.cpp | ||
| debug_density_field_renderer.hpp | ||
| main.cpp | ||
| projection.cpp | ||
| projection.hpp | ||
| readme.md | ||
| renderer.cpp | ||
| renderer.hpp | ||
| shader.cpp | ||
| shader.hpp | ||
| sim_params.hpp | ||
| simulation.cpp | ||
| simulation.hpp | ||
| sph_math.hpp | ||
| ui.cpp | ||
| ui.hpp | ||
ParticleSim — SPH Fluid Simulation
A real-time Smoothed-Particle Hydrodynamics (SPH) fluid simulation written in C++17 with OpenGL. Particles are rendered as lit sphere impostors, colored by speed, inside an adjustable bounding box with a live ImGui control panel.
Branches / Feature Variants
This project ships three different implementations of the same simulation, each living on its own branch. Pick the branch for the variant you want before building.
| Branch | Variant | Description |
|---|---|---|
main |
2D — multithreaded CPU | Reference SPH solver running on the CPU, parallelized with OpenMP. Uses an std::unordered_map spatial hash and runs the pressure / viscosity / integration passes across threads. |
compute-shader |
2D — GPU compute | The 2D solver ported to OpenGL compute shaders. The full SPH pipeline (hashing, density, pressure, viscosity, integration) runs on the GPU. |
add-3d |
3D — GPU compute | Full 3D solver on GPU compute shaders, with an orbit camera, 3D spatial hash, and a sphere-impostor renderer that reads positions straight from the particle SSBO. |
To switch variants:
git checkout main # 2D CPU (multithreaded)
git checkout compute-shader # 2D GPU compute
git checkout add-3d # 3D GPU compute
Note: the build steps below are the same on every branch. The GPU compute branches (
compute-shader,add-3d) require an OpenGL 4.3+ context for compute shader support; the CPUmainbranch does not, but a modern context is still used for rendering.
Prerequisites
You need a C++17 toolchain, CMake, and the following libraries:
- CMake ≥ 3.10
- A C++17 compiler (GCC, Clang, or MSVC)
- OpenGL (4.3+ driver recommended, required on the compute branches)
- GLFW 3 (windowing / input) — must be discoverable by
find_package(glfw3) - OpenMP (used by the CPU solver and the build links it on all branches)
The following are vendored and expected to live inside the project tree (the build references them directly), so make sure they are present:
- GLAD at
glad/— withglad/glad.cand headers underglad/include/ - Dear ImGui at
imgui/— core sources plusimgui/backends/imgui_impl_glfw.cppandimgui/backends/imgui_impl_opengl3.cpp
If you cloned the repo and these folders are missing, fetch them (e.g. download a GLAD loader for OpenGL 4.3 Core and clone Dear ImGui into imgui/) before building.
Installing the system dependencies
Ubuntu / Debian
sudo apt update
sudo apt install build-essential cmake libglfw3-dev libomp-dev libgl1-mesa-dev
macOS (Homebrew)
brew install cmake glfw libomp
Build
From the repository root:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
The build produces a single executable named ParticleSim (in build/, or build/Release/)
Run
./build/ParticleSim
A 1920×1080 window opens with the simulation running immediately and the ImGui parameter panel docked in the top-left.
Controls
These apply to the 3D branch (add-3d); the 2D branches use a subset (no camera orbit).
- Middle mouse + drag — orbit the camera around the scene
- Scroll wheel — zoom in / out
- Right mouse button — apply an interaction force that pulls particles toward the interaction point
- ImGui panel — tune gravity, damping, bounding box, particle count, and SPH parameters (smoothing radius, target density, pressure, near-pressure, viscosity) live
- Reset Defaults / Restart Simulation — reinitialize the particle layout
Tuning notes
- Particle count is capped at compile time in
main.cpp(maxParticles = 40000); the ImGui slider adjusts the active count within that cap. Changing it triggers a re-seed of the grid. - SPH stability is sensitive to the relationship between
smoothingRadius,targetDensity, and the pressure multipliers. If the fluid explodes, lower the pressure multiplier or the timestep, or raise the smoothing radius. - The physics runs on a fixed
1/60 stimestep with a single substep per frame.
Project layout
| Area | Files |
|---|---|
| Entry point / main loop | main.cpp |
| GPU compute solver | gpu_sim.cpp / gpu_sim.hpp |
| GPU particle renderer | gpu_renderer.cpp / gpu_renderer.hpp |
| CPU solver | simulation.cpp / simulation.hpp |
| SPH kernels (CPU) | sph_math.hpp |
| Window / GL setup | renderer.cpp / renderer.hpp |
| Bounding-box renderer | bounds_renderer.cpp / bounds.hpp |
| Debug density field | debug_density_field_renderer.cpp |
| Camera / matrix math | projection.hpp |
| Shader helpers | shader.cpp / shader.hpp |
| ImGui panel | ui.cpp / ui.hpp |
| Simulation parameters | sim_params.hpp |
| Build | CMakeLists.txt |