For the proposal of the final project, I want to implement a real time interactive IISPH Solver based on the following papers:
- A Parallel Architecture for IISPH Fluids by Felix Thaler, Barbara Solenthaler, and Markus Gross. Reference video
- Real-Time Incompressible Fluid Simulation on the GPU by Xiao Nie, Leiting Chen, and Tao Xiang
Reach goal: Implementing the graphics pipeline using Vulkan.
- TBB optimization: After I added TBB, runtime to compute for each frame is reduced by half (see Performance Analysis section below)
- OpenVDB export + meshing
- Solid interaction
- Fluid tank
- Ability to save screenshot every frame into bmp
- IISPH
- GPU Optimization
- Index sorting
- Pressure force field
- Viscosity force field (change value inside scene.json)
- Press Space to pause simulation
- z-indexing
Currently my simulation is running on the CPU still so it's pretty slow. The only tbb call is in SPHSolver::Update (in SPHSolver.cpp), that update the particle velocity & position using parallel_for (not even sure if this is worth any extra credits);
I implemented the SPH Solver with naive neighbor search. When you started running the code, you'll see a test particle iterating through the grid and shows all the neighbors in red color. However, this neighbor search isn't using a working uniform grid yet.
I have a simple test suite in main.cpp to test Poly6. Currently spiky kernel and viscous kernel are not tested. By uncommenting #define UNIT_TEST
, there should be print out of the kernel unit testing.
Korra is a cross-platform C++ fluid SPH solver, designed and built for CIS563 course at the University of Pennsylvania, Sprin 2016, instructed by Debanshu Singh. Korra uses OpenGL heavily for the graphics pipeline. It is also designed for GPU optimization for fluid advection.
Details will be updated as more features are coming soon.
./install.sh
The application Korra
will be created in build folder. Simply run ./Korra
to launch.
- Clone using git clone --recursive [email protected]:trungtle/KorraFluidSolver.git
If you forgot to call --recursive, you can recover the submodules by
cd CIS563-FluidSolver (at top directory)
git submodule update --init --recursive
There should be 2 submodules for jsoncpp
and nanogui
- Compile nanogui with cmake and make
cd src/thirdparty/nanogui
cmake -G "Unix Makefiles" .
make
- Compile Korra with cmake and make
cd ../../../ (at top directory)
mkdir build
cd build
cmake -G "Unix Makefiles" ../
make
- Launch
./Korra
The following are classes for the fluid solver.
The Viewer class contains all the OpenGL, glfw, glew, shader programs, and scene initialization. Once the the initialization is completed, the Viewer kicks the simulation loop. The loop can be canceled by hitting the ESC key.
- Note: By defining #define TEST_SCENE in
viewer.h
andscene.h
, the test scene would be used instead.
The Scene class contains the Camera and all other objects in the scene. The Scene class takes in a json file in the scene/
directory for initializing the fluid solver. In this case, it's the scene.json
file.
There are three objects of our interests:
-
m_fluidContainer, a Box object that specifies the boundary of the fluid.
-
m_fluidGeo, a FluidGeo object that specifies the particles of the fluid.
-
m_fluidSolver, a FluidSolver object that gets updated every simulation frame to compute the fluid state.
-
Note: By defining #define TEST_SCENE in
viewer.h
andscene.h
, the test scene would be used instead.
The ShaderProgram compiles the glsl/simple.vert
vertex shader and the glsl/simple.frag
. This program is used to draw simple geometry without any special shading.
The ParticleAdvectProgram compiles the glsl/particle_advect.vert
, glsl/particle_advect.frag
, glsl/particle_draw.frag
, and glsl/particle_draw.frag
into 2 programs: m_programAdvect
and m_programDraw
.
This class is used to perform two render passes for transform feedback. In short, the first pass uses the particle_advect.vert
to update particle positions but skipping the rasterization phase, passing its vertex attributes directly to the partice_draw.vert
and particle_draw.frag
for the actual drawing. This approaches allow us to parallelize the particle update using only the shaders.
The Camera class handles the view matrix. The Camera class uses the KeyboardControl class to handles user keyboard input. To control the Camera movement, uses:
- W: Pan up
- S: Pan down
- A: Pan left
- D: Pan right
- Up: Look up
- Down: Look down
- Left: Look left
- Right: Look right
The Geometry is the base class for all the drawable geometry classes in a scene. It is not meant to be instanced directly but to be derived by new classes (etc. Box and FluidGeo). Geometry class contains all the information for transformations, vertex buffers, vertex arrays, index buffer, and drawing mode.
Each new geometry instanced NEEDS to call Create() in order to properly initialize its data.
This class supports the basic affine transformation:
- Translate
- Rotate
- Scale
This class supports three drawing mode:
- Wireframe (GL_LINES)
- Shaded (GL_TRIANGLES)
- Vertex (GL_POINTS)
Box is derived from Geometry. Box represents a simple box geometry.
FluiGeo is derived from Geometry. FluiGeo represents a collection of fluid particles. FluidGeo also contains the particle positions and velocities.
FluidSolver initializes all the particle information such as container boundary and particle separation. Its Update()
function is called each frame to update the solver if needed.
KeyboardControl handles user keyboard input.
Starting with main.cpp
, the Viewer is initialized, then the simulation loop kicks in. For each frame, the Scene calls its Update()
and Draw()
functions to update the state of the solver then render the result.
I improved the performance around calls to tbb::parallel_for when searching neighbors, and tbb::parallel_reduce for computing density, pressure gradient, and viscosity.
To solve fluid per frame:
- Without TBB: ~338ms
- With TBB: ~137ms
See Camera class section above.
See LICENSE.md for the MIT License.