Bioluminescence

Animation project

by Tiago Maranhao Christine Wolf

Simulation

Dev Blog

One: beginnings

This is the final project for the course "Computer Graphics and Interaction" by professor Cristopher Peters, at KTH Royal Institute of Technology, during the Spring of 2023.

The initial inspiration came from a previous project by Christine, called ABSORB, which was all about creating an immersive experience exhibition centered around water and light. It was the motivation to explore the idea of animating glowing water in a new and unique way. Thinking about glowing water the thought was not far away: bioluminescence! The natural phenomena of bioluminescent organisms would be a wonderful topic for the computer graphics project. The idea was discussed with the professor, who provided us with some valuable advice. It was suggested by him that using a particle system would be a relevant approach to achieve the desired effect.

Originally, Tiago thought about doing the project about fluid simulation, and Christine, about simulating bioluminescent plankton. Then we realized it would be amazing to combine efforts and build a fluid simulation and bioluminescent particles simulation on top of it! That’s how this

We realized that we could take it up a notch by making the project touch-sensitive on a large screen, creating an interactive experience. This aspect excited us because we wanted to push the boundaries and engage the audience in a whole new way. Moreover, we decided to focus on the research aspect of the project to deepen our understanding and contribute to the existing knowledge.

Two: specification

We started specifying the project using the specification template provided by our professor. This helped us to outline the main goals and requirements for the project. We wanted to ensure that we had a clear direction and a solid foundation to build upon. The template served as a great starting point and helped us organize our thoughts and ideas effectively. It was essential to lay the groundwork for the research and report.

Three: technical inspirations

With out specification, we could start getting our hands "dirty". We looked up for implementations of Fluid Simulation, and found many interesting resources. Some very inspirational, but without much explanation, and others very didactic, with detailed explanations.

Inspirational (fluid simulation)

Fluid simulation explained

The Navier-Stokes equations

Particle Systems and Flow Fields

Inspirational (bioluminescence)

Shots from Studio Roosegaarde's project with bioluminescence.. we see a hand touching water and bright particles spreading out of it

Four: our strategy

Going through all these references, we decided to divide our implementation into the following steps:

  • build a classic fluid dynamics simulation with the Navier-Stokes equations for incompressible flow, resulting in a fluid velocity grid
  • use this velocity grid as a vector field to move a particle system built on top of the fluid simulation, representing the bioluminescent plankton
  • make the simulation interactive by allowing touching/clicking to generate new particles, and dragging to change the velocity field realistically
  • parameterize the particle system to simulate the bioluminescence behavior

Five: the fluid simulation

We based our implementation on the ones by Mike Ash and Jos Stam. We begin by considering a two-dimensional discrete representation of the fluid in a square container. The container is represented by a squared homogeneous grid, with N cells on each side. For each grid cell, the idea is to compute and keep track of values for two variable: density (scalar) and velocity (vector), and we assume that these values are constant within a cell.

A hand drawn grid of cells, with velocity vectors plotted on it

The Navier-Stokes equations provide a precise description of the evolution of a velocity field over time. Since a velocity field by itself is not something visually interesting, we can make the actual fluid "visible" by modeling its particles as a density field (scalar) that evolves through the velocity vector field.

This is important because we noticed that a common pattern in simulating fluids is computing some variable's value for a given cell by taking its previous value and applying some factor over the sum of the current values of its immediate neighbors, like so:

A hand drawn grid of cells, with velocity vectors plotted on it

We wanted our simulation to be accessible from any device, so we chose to implement it using the Web Standards: HTML, CSS and (vanilla) Javascript. We used the HTML5 Canvas API for drawing. Our plan is to code everything from scratch, whenever possible, to maximize our learning!

So, we started creating basic classes and methods for representing things such as vectors and vector operations, and the moved on to the simulation itself. We tried to keep everything as parameterized as possible, so that we could tinker with the key aspects of the simulation.

To actually visualize the simulation, we mapped each cell to an actual square on the screen, mapping the cell's current density to the square's color's intensity. We started with a small grid (for fear of things blowing up), until we were sure that the simulation was behaving as expected. To test the simulation, we added interactivity right away: clicks for "spreading" density (that is, increasing the density's value on the clicked cell) and mouse drags for creating movement (by increasing the velocity vectors along and in the direction and intensity of the mouse's motion).

After many, many errors, and after figuring out why the errors were gone but nothing was apparently happening, we finally got the simulation working for a very small grid:

A hand drawn grid of cells, with velocity vectors plotted on it

It doesn't look exciting now, but for us it was super exciting to see something work for the first time! Below, a video of this first prototype (with a slightly larger grid).

We can see the effect of using larger and larger grids (meaning, smaller and smaller cell sizes: 20, 10 and 5px).

The fluid simulation results in basically a varying velocity vector field, so we wanted to visualize that field. For that, we plotted the velocity vectors for each cell, and that is what we got:

A grid of cells, with velocity vectors plotted on it

Next step was to include an interface to dynamically interact with the key simulation parameters:

A grid of cells, with velocity vectors plotted on it

And finally we were satisfied with our fluid simulation, and could move on to the next step: the particle system.

Six: the particle system

Now that the fluid simulation has been successful, we had a velocity field that changes over time and in response to user interaction. The next step is setting up a system of particles that move over the fluid according to the underlying vector field. According to the definition of William Reeves,

"A particle system is a collection of many many minute particles that together represent a fuzzy object. Over a period of time, particles are generated into a system, move and change from within the system, and die from the system"

We took advantage of JavaScript's object-oriented programming capabilities to define a class of particles, and then create each particle as an instance of this class, encapsulating their own state, data, and parameters. This allows for a great level of randomization and control, and thus individualization of the particle's behavior.

Screenshot from a code editor, where the simplified code for our particle class is shown

In our model, particles are created around the clicked or touched point. After that, their motion will be determined by the velocity vector field. That is, we check over which cell each particle lies, and we use the cell's velocity vector to compute the particle's velocity and next position.

We started our tests with only two particles. In the video below, we keep the vector field visible (actually, the directions of the vector field, the magnitudes are not represented) and we also keep adding density to the underlying fluid with our mouse clicks.

With the combination of different parameters, the possibilities seemed endless. Sizes, shapes, colors, transparencies, fading rates, size change rates, number of particles, radius of particle generation, velocity change rate... Tinkering with them would yield very different results.

Although not what we were aiming for, many combinations generated some quite aesthetically pleasant patterns!

To mimic the natural behavior, we needed to carefully tweak some of those key parameters!

Final: refining — iterating

Once the basic framework of the implementation was in place, we wanted to improve the realistic behavior of the interaction. To do this, we looked at the various basic factors that determine the behavior, and we made those factors available to real-time adjustements in the user interface:

Screenshot of the user interface for adjusting the key parameters of the simulation

The iteration process was very intuitive and we compared our animation with the behavior of the plankton from various videos. The key factors were as follows:

  • Shape
  • Glow
  • Color
  • Size
  • Glow off effect

We made notes of the process. After the iteration and the implementation of the changed default factors, we again discussed small improvements. Among other things, we changed the color of the particles and the size. This was because a small particle size looked more natural.

Picture of an open notebook with many notes written on it

As a final touch, although our fluid simulation is mainly used to drive the bioluminescent particles, to avoid moving these particles simply over a flat dark background, and to add some texture and convey some sense of the underlying fluid motion, we set up an initial random density distribution, representing its intensity with dark blue shades. Particularly, we set up the initial density distribution using two-dimensional Perlin Noise, to achieve a subtle, smooth, and realistic effect.

This was a very satisfying journey! Naturally, there many opportunities for improvements. As we noted specially in the final days of the project, small tweakings in the parameters can affect greatly the resulting appearance. This way, a perception study could improve greatly the realism of the simulation. Beyond that, there is the technical challenge of using GPU programming, such as WebGL, to improve the performance and allow more advanced effects on the individual particles.

All in all, we are tremendously proud of our work and collaboration!