Version 3 — © 1996-1999 Christian Cohnen
Originally a Java applet (1996). The original Java applet code was transpiled to JavaScript/Canvas in 2026 so the effect can run in modern browsers without a Java plugin. The JavaScript version uses Canvas pixel manipulation with an indexed 128-entry color palette.
The ParticleFire applet uses a particle system to create a real-time fire effect. Particles spawn at the bottom of the applet area with random positions, velocities and luminance values. Each particle rises upward at an individual speed while following a configurable sinus wave oscillation for horizontal movement. As a particle travels, its luminance fades over time until it expires and respawns. The resulting intensity field is smoothed each frame by a weighted averaging filter that blends each pixel with its left, right and lower neighbors — this convolution kernel produces the characteristic soft, glowing flame shape. The final pixel colors are looked up from a 128-entry gradient palette that interpolates across five user-definable color stops.
Each frame, every pixel is recalculated from its neighbors using the following steps:
f = pixel_below * 252
f = f >> 7 // ≈ pixel_below × 1.97
f = f + pixel_left
f = f + pixel_right
f = f >> 2 // divide sum by 4
This produces an asymmetric kernel where the pixel below dominates — pulling heat upward — while left and right neighbors provide horizontal diffusion:
| row | left | center | right |
|---|---|---|---|
| current row | 0.25 | – | 0.25 |
| row below | – | 0.492 | – |
| total | 0.992 | ||
The pixel below carries weight 252 / 128 / 4 = 0.4921875, not exactly 1/2.
Because the total (0.992) stays below 1.0, the field loses roughly 0.8% of its energy each frame — flames cool down automatically as they rise.
The only multiplication (* 252) can be decomposed into (val << 8) − (val << 2), meaning the entire filter runs on shifts and additions alone.
The underlying technique has its roots in the demoscene of the late 1980s and early 1990s, where fire effects were hand-coded in assembly language on home computers like the Atari ST and Amiga.
Even the C64 ran variations of the effect using ASCII characters.
This particular implementation was inspired by flap^Capacala's fire effect from the MS-DOS demoscene — the Capacala group produced several influential demos on the PC platform in the mid-1990s that showcased optimized real-time fire routines.
Key tricks were to avoid expensive multiplications in the convolution filter entirely — all weighting and averaging was done with bit-shift operators (>>) instead, which cost only a single CPU cycle compared to dozens for a multiply on these processors — and to use loop unrolling, where the inner filter loop was manually expanded to process multiple pixels per iteration, eliminating branch overhead and keeping the CPU pipeline filled.
This applet preserves the classic shift-based approach in its filter kernel.
What once required cycle-counted 68000 or 6502 assembly to run in real time has since evolved into a staple of modern video editing and motion graphics, where particle-based fire simulations appear in far more complex forms.
Color values use hex notation, e.g. #FF8800. The five color parameters define a gradient from background to flame tip.
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
link | URL | Link target when applet is clicked | null | no |
targetWindow | String | Target window for link (_blank, _parent, etc.) | _self | no |
image | URL | Overlay image (use a transparent GIF) | – | no |
image2 | URL | Overlay image on mouseover | – | no |
particles | int | Number of particles (max 2048) | 500 | no |
sinus | int | Sinus movement amplitude of particles | 16 | no |
backColor | Color | Background color | #000000 | no |
lowColor | Color | Low intensity color | #202040 | no |
midColor | Color | Mid intensity color | #805050 | no |
upColor | Color | High intensity color | #FFD0B0 | no |
endColor | Color | Tip/end color | #FFFFFF | no |
<applet archive="ParticleFire.jar"
code="ParticleFire.class" height="120" width="100">
<param name="sinus" value="16">
<param name="particles" value="512">
</applet>
The JavaScript port uses the same algorithm — shift-based convolution filter, particle system with sinus oscillation — but renders into an HTML5 <canvas> via ImageData.
Additionally, mouse interaction lets you spawn fire particles by moving the mouse over the canvas, and the scroll wheel adjusts the number of active particles in real time.
<canvas id="game" width="100" height="120"></canvas>
<script>var PARTICLEFIRE_CFG = { particles: 512, sinus: 16 };</script>
<script src="particlefire.min.js"></script>
| Name | Type | Description | Default |
|---|---|---|---|
particles | int | Number of particles (max 2048) | 500 |
sinus | int | Sinus movement amplitude | 16 |
backColor | string | Background color hex | "#000000" |
lowColor | string | Low intensity color hex | "#202040" |
midColor | string | Mid intensity color hex | "#805050" |
upColor | string | High intensity color hex | "#FFD0B0" |
endColor | string | Tip/end color hex | "#FFFFFF" |
image | string | ID of hidden overlay <img> element | null |
image2 | string | ID of hidden mouseover overlay <img> element | null |
link | string | URL to open on click | null |
targetWindow | string | Target window for link | "_self" |
scrollStep | int | Particles added/removed per scroll line | 10 |
Moving the mouse over the canvas injects fire particles at the cursor position — drag to paint with fire.
The scroll wheel adjusts the number of active particles: scroll up to add more, scroll down to reduce.
The scrollStep parameter controls how many particles are added or removed per scroll line.
Originally a Java applet (1996). The original used Java's MemoryImageSource
with an IndexColorModel for pixel-level rendering. The JavaScript version uses Canvas
ImageData with a Uint32Array view for equivalent pixel manipulation.
The shift-based convolution filter is preserved exactly from the original.