Smoke Simulator/Volumetric Renderer
A Semi-Lagrangian smoke simulation system and integrated volumetric renderer
A frame from from a 100x100x100 size grid smoke simulation, rendered with a pseudo-blackbody effect with my volumetric renderer.

One of the spring 2012 CIS563: Physically Based Animation assignments was a semi-Lagrangian smoke simulator based on the MAC-grid advection approach described in the SIGGRAPH 2007 Fluid Simulation course notes. I extended the project to include multithreading, RK4 integration, better support for extremely large simulation grids, and added a volumetric renderer with a pseudo-blackbody lighting system. The volumetric renderer can be run either separate from the simulator, or as an integrated component rendering frames as soon as they are simulated. This project is written entirely in C++.

Base Code

The simulator component of this project utilizes base code written by Aline Normyle and Peter Kutz for CIS563: Physically Based Animation. The volumetric renderer component was written from scratch and utilizes no base code.


Semi-Lagrangian Smoke Simulation: The simulation works in a semi-Lagrangian fashion by advecting densities and temperatures through a MAC grid structure and solving smoke states using a pre-conditioned conjugate gradient solver based on the method described in Robert Bridson's 2007 SIGGRAPH Fluid Simulation Course Notes.

Large grids: The simulator supports extremely large grids (100x100x100 and larger) by using a sparse MAC grid representation that only stores grid cells that contain nonzero values in memory.

Multiple Integration Schemes: The simulator supports Euler and fourth-order Runge-Kutta integration, and allows switching between the two methods on the fly.

Live Preview: The simulator comes with an OpenGL preview complete with interactive camera and built in screen recording and simulation debugging tools, including support for visualizing advection directions and velocities in realtime.

Architecture: Both the smoke simulator and volumetric renderer compile without modification on OSX, Windows, and Fedora Linux, and both are multithreaded using OpenMP. Both the simulator and renderer use stb_image for image output and GLM for linear algebra operations.

Raymarching Volumetric Renderer: Included with the simulator is a custom, written from scratch raymarching volumetric renderer capable of acting as an integrated renderer with the simulator, and capable of reading in volumetric data from disk and running as a standalone renderer. Uses the Beer-Lambert Law to model light absorption in a volume of heterogeneous density, and includes optional trilinear and tricubic density interpolation.

Multiple Light Sources: The renderer supports an arbitrary number of light sources of arbitrary intensity and color.

Pseudo-Blackbody Illumination: Volumetric data can be rendered with self-illumination provided by a pseudo-blackbody radiation effect using an exponential falloff function to simulate light emission and attenuation within volumes of heterogeneous density.

Procedural Noise: The volumetric renderer can generate and render volumetric clouds using procedural noise functions such as Perlin/Simplex noise when running in standalone mode.

Maya Integration: Maya integration is supported through a Python script that sends spheres modeled and positioned in Maya as boundary conditions for volumetric renderer procedural cloud generation.

Selected Images and Videos

A procedurally generated cloud, rendered with my volumetric renderer.
An cloud rendered with my volumetric renderer with pseudo-blackbody illumination.
A smoke simulation running on a 100x100x100 size grid, rendered with a pseudo-blackbody effect with my volumetric renderer.
A smoke simulation running on a 100x100x50 size grid, visualized with the simulator's live OpenGL view.
A procedurally generated cloud, created with Simplex noise and animated in Maya, rendered with my volumetric renderer.
An expanding cloud rendered with my volumetric renderer with pseudo-blackbody illumination.

This project would not be possible without the guidance of Dr. Joseph T. Kider, the instructor for CIS563 in the spring of 2012. Additionally, the volumetric renderer component of this project was derived from CIS460/560, taught by Professor Norm Badler. I would also like to thank CIS563 TAs Tiantian Liu and Peter Kutz. Friends Gabriel Leung and Dan Knowlton acted as sounding boards for various ideas and discussed ideas.

Project Blog Posts

Progress updates for this project were posted to my development blog, Code & Visuals. The following posts detail the development of this project. Posts are listed starting with the most recent:


In the process of building my simulator, I drew upon the following papers, and articles. They are listed in no particular order.

SIGGRAPH 2007 Fluid Simulation Course Notes: An extremely comprehensive set of notes detailing semi-Lagrangian based fluid simulation, by Robert Bridson and Matthias Muller-Fischer.

Fluid Simulation for Computer Graphics: The go-to reference book for fluid simulation, by Robert Bridson.

Preconditioner Wikipedia Article: An article summarizing how mathematical preconditioners work.

Runge-Kutta Methods Wikipedia Article: A fairly concise summary of the Runge-Kutta integration schemes, including RK4

SIGGRAPH 2011 Production Volume Rendering Course Notes: An extremely comprehensive set of notes detailing volumetric rendering by Magnus Wrenninge and Nafees Zafar.

Beer-Lambert Law Wikipedia Article: An article summarizing the mathematics and physics of Beer-Lambert absorption.

Display of Surfaces from Volume Data: The 1988 Marc Levoy paper introducing volume rendering