Korra Fluid Solver, CIS 563, University of Pennsylvania, Spring 2016
Update April 15 (Final project)
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.
Update April 10 (Sprint 3)
- 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
- GPU Optimization
- Index sorting
Update March 30 (Sprint 2)
- Pressure force field
- Viscosity force field (change value inside scene.json)
- Press Space to pause simulation
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);
Update March 23 (Sprint 1)
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.
Automatic build (easy!)
Korra will be created in build folder. Simply run
./Korra to launch.
Manual build (if you prefer doing it manually)
- Clone using git clone --recursive email@example.com: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
- 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
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
scene.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
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
scene.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_draw.frag into 2 programs:
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
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:
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.
main.cpp, the Viewer is initialized, then the simulation loop kicks in. For each frame, the Scene calls its
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.