Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
This branch is 64 commits ahead, 3 commits behind debanshusingh:master.

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Korra Fluid Solver, CIS 563, University of Pennsylvania, Spring 2016

Youtube Link Rendered 1 Rendered 2 GUI

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:

Reach goal: Implementing the graphics pipeline using Vulkan.

Update April 10 (Sprint 3)

Completed features:

  • 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

Incomplete features:

  • GPU Optimization
  • Index sorting

Update March 30 (Sprint 2)

Completed features:

  • 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);

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!)


The application Korra will be created in build folder. Simply run ./Korra to launch.

Manual build (if you prefer doing it manually)

  1. Clone using git clone --recursive

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

  1. Compile nanogui with cmake and make
cd src/thirdparty/nanogui
cmake -G "Unix Makefiles" .
  1. Compile Korra with cmake and make
cd ../../../ (at top directory)
mkdir build
cd build
cmake -G "Unix Makefiles" ../
  1. Launch


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 and 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 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 and 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_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.

Code flow

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.

Performance Analysis

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

Camera control

See Camera class section above.


See for the MIT License.

Third Party


No description, website, or topics provided.







No releases published


No packages published


  • C++ 67.3%
  • HTML 27.7%
  • C 4.7%
  • JavaScript 0.2%
  • CSS 0.1%
  • Objective-C 0.0%