Introduction
The plasma effect is one of the most iconic visual effects from the demoscene era of the 1980s and 1990s. Named for its resemblance to flowing plasma or aurora-like patterns, this effect creates organic, continuously moving patterns using surprisingly simple mathematics. Despite its simplicity, the visual result is captivating and has remained a favorite demonstration of procedural graphics techniques.
The effect relies on combining multiple sinusoidal wave patterns to create complex interference patterns. By animating these patterns over time and mapping them to color gradients, we achieve the characteristic flowing, pulsing appearance.
On early hardware like the Commodore 64 and Amiga, plasma effects often used pre-calculated lookup tables to avoid expensive real-…
Introduction
The plasma effect is one of the most iconic visual effects from the demoscene era of the 1980s and 1990s. Named for its resemblance to flowing plasma or aurora-like patterns, this effect creates organic, continuously moving patterns using surprisingly simple mathematics. Despite its simplicity, the visual result is captivating and has remained a favorite demonstration of procedural graphics techniques.
The effect relies on combining multiple sinusoidal wave patterns to create complex interference patterns. By animating these patterns over time and mapping them to color gradients, we achieve the characteristic flowing, pulsing appearance.
On early hardware like the Commodore 64 and Amiga, plasma effects often used pre-calculated lookup tables to avoid expensive real-time sine calculations. Modern GPUs can compute these effects in real-time with minimal performance impact, allowing for more complex variations and higher resolutions.
Core Mathematics
At its heart, the plasma effect combines multiple sine and cosine functions with different frequencies and phases. The basic approach involves:
- Generating wave patterns: Create 2D wave patterns using sine and cosine functions based on screen coordinates
- Combining waves: Add or multiply multiple wave patterns to create interference effects
- Time animation: Offset the wave patterns over time to create motion
- Color mapping: Map the resulting values to a color gradient
The typical formula structure looks like:
value = sin(x + time) + cos(y + time) + sin(distance + time)
Where different combinations of x, y, distance, and time create different visual patterns.
Wave Interference
The beauty of the plasma effect comes from wave interference. When multiple sinusoidal patterns overlap, they create complex patterns through constructive and destructive interference:
- Constructive interference: Waves align and amplify each other
- Destructive interference: Waves cancel each other out
This creates the characteristic peaks and valleys that define the plasma’s flowing appearance.
Color Gradients
The numerical output of the combined sine waves is then mapped to colors. A common approach uses the cosine color palette technique, which provides smooth, continuous color gradients by treating the wave output as input to RGB color channels with different phase offsets.
Specular Enhancement
Modern implementations can add specular highlights by analyzing the gradient of the color field. This creates the illusion of a reflective surface and adds depth to the otherwise flat 2D pattern.
The specular component is typically implemented using derivatives (dFdx and dFdy in GLSL) to detect rapid color changes, treating these as “surface normals” for lighting calculations.
Implementation
Below is my implementation of the above in GLSL along with a live preview of the effect.
// by Nikos Papadopoulos, 4rknova / 2016
// Specular highlights contributed by Shane
#define SPECULAR
#define SCALE 1.0
void mainImage(out vec4 col, in vec2 pc)
{
float time = iTime;
vec2 a = vec2(iResolution.x /iResolution.y, 1);
vec2 c = SCALE * pc.xy / iResolution.xy * a * 4. + time * .3;
float k = .1 + cos(c.y + sin(.148 - time)) + 2.4 * time;
float w = .9 + sin(c.x + cos(.628 + time)) - 0.7 * time;
float d = length(c);
float s = 7. * cos(d+w) * sin(k+w);
col = vec4(.5 + .5 * cos(s + vec3(.2, .5, .9)), 1);
#ifdef SPECULAR
col *= vec4(1, .7, .4, 1)
* pow(max(normalize(vec3(length(dFdx(col)),
length(dFdy(col)), .5/iResolution.y)).z, 0.), 2.)
+ .75;
#endif
}