WebGL Ripples
by Dylan Cutler (DCtheTall)
Summary
This repo contains source code for an interactive water ripple effect created
using WebGL. Click here for a live demo.
Algorithm
In nature, wave propagation is given by the wave equation, a second order partial differential equation:
where is the Laplace operator. If we treat as unity, we can simplify the PDE to
To simulate waves, the program numerically solves the differential equation above using Verlet integration, a method for iteratively solving second order ordinary differential equations of the form:
In this case is a convolution with the discrete Laplace operator, given by the kernel:
Verlet integration solves the ODE iteratively using the following formula:
where the convolution of the height map discrete Laplace operator. For simplicity, the program treats as unity.
Afterwards, linear damping is applied to the wave so that it dissipates over time.
Implementation
In order to compute the next iteration for Verlet integration, I needed to keep the 2 most recent iterations of the height map then map the result to a 3rd height map. That height map was sampled in a water shader which added Phong global illumination and refraction using ray tracing to make the water appear realistic.
The source code is implemented almost entirely in TypeScript and GLSL using a TypeScript WebGL abstraction layer I have been working on. This API is build for iteratively applying shaders you write yourself.
The shaders that use glslify can be modular, so this API is more focused on applying shader programs to a WebGL scene.
License
The code in this repository is released under an Apache 2.0 license and is the copyright of Google Inc.
It is available for free and fair use. See the LICENSE for more information.
Improvements
Really the same effect can be achieved with just one heightmap which uses each of the red, blue, and green channels to keep track of the 3 most recent states of the water height.
A Guassian blur on the stone texture may make it look better.
Also the water shader breaks on certain GPUs on Linux machines for some reason. I have not tested it on Windows.