NatureGL Firev1.0.0

Guides

Fuel, heat and smoke

Every voxel stores temperature, fuel and smoke. Emitters add fuel and heat, hot fuel burns, and burning releases more heat, soot and volume. The flame you see is gas above the glow threshold, coloured by a blackbody ramp.

#The combustion model

The state pass runs once per simulation step, for every voxel. After the three fields are advected:

  1. Inject. Emitters and bursts add fuel and smoke, and raise the temperature to at least their own temperature. Emitters ignite what they inject.
  2. Burn. Fuel burns at params.burnRate, but only where the gas is hot enough. The ignition ramp runs from T = 0.3 to 0.55.
  3. Release. Each unit of burnt fuel adds heat (×1.25), soot (×0.55 × params.smoke) and volume. The volume becomes the combustion expansion in the pressure solve (× params.expansion).
  4. Cool and fade. Temperature loses 0.3·T + 0.28·T³ per second, scaled by params.cooling. Smoke and fuel dissipate slowly, and everything fades near the side and top walls, so nothing piles up at the edge of the box.

The fields are clamped to temperature 0–1.7, fuel 0–12 and smoke 0–6. Hot gas rises with 9.5 × params.buoyancy × T, and smoke weighs it down a little. Obstacle cells are always empty.

#The dials

These are the seven sliders in the demo. All are multipliers with a default of 1.

ParamDemo rangeTurn it up for
wind−4 … 4Horizontal wind in m/s (default 0). See Wind and obstacles
turbulence0 … 2More noise forcing and stronger vorticity confinement: a busier, curlier flame
cooling0.2 … 3Shorter flames that turn to smoke sooner
expansion0 … 3More volume from burning: flames that spread and puff, bigger bursts
buoyancy0 … 3Faster-rising, taller flames
smoke0 … 2.5More soot from emitters, bursts and burning
intensity0.2 … 3Brighter flame emission and a brighter fire light
js
fire.setParams({ cooling: 1.4, buoyancy: 1.2 });   // merge
fire.params.smoke = 0.4;                           // params is live: mutate it directly
plume: a 0.8 emitter temperature, smoke: 1.8 and an emitter smoke rate of 7. It smoulders more than it burns.
campfire: a 1.1 emitter temperature, smoke: 0.8 and a low emitter smoke rate. The flames stay clean and bright.

#Flame look

The raymarcher turns the fields into colour. None of these affect the simulation.

ParamDefault
emission3.2Base flame emission, × intensity
flameThreshold0.34Temperature where gas starts to glow
flameAbsorption1.5Flame extinction. Higher values make the cores opaque
kelvinBase, kelvinScale1100, 1800Maps T to kelvin for the blackbody ramp
blueBase1The blue premixed glow where fuel is burning
licks0.55Sub-grid flame tongues: two octaves of rising noise at the hot edge
detail2.8Sub-grid noise displacement in cells, scaled with the grid
smokeDensity2.6Smoke extinction
smokeAlbedo0.62Single-scattering albedo of the smoke
smokeColor'#ffffff'Smoke tint

Hot soot is drawn thin. Smoke only shows at full density once it has cooled, so you don't get dark smoke inside the flame.

#The blackbody ramp

Flame colour comes from a lookup texture that integrates Planck's law from 380 to 780 nm against the CIE 1931 observer (the Wyman, Sloan and Shirley multi-lobe fit) and converts to linear sRGB. It covers 500 K to 4000 K. The fire light uses the same ramp, so the light always matches the flame. You can use it yourself:

js
import { blackbodyRGB, kelvinToColor } from 'naturegl-fire';

blackbodyRGB(1800);                            // [r, g, b, Y]: normalised linear sRGB + relative luminance
kelvinToColor(2400, lampLight.color);          // write straight into a THREE.Color

#Smoke lighting

The light-volume pass stores three things per voxel. They are the transmittance toward the key light, the shadowed and distance-attenuated fire light, and the transmittance straight up. The upward term self-shadows the ambient light, so the inside of thick smoke darkens instead of glowing flat.

ParamDefault
selfShadowtrueSmoke and flame shadow themselves in the light volume. Off, all three terms are unshadowed
shadowDensity2.2Extinction used for that shadowing

The key light is a direction plus a colour, set with setLighting(). The demo points it at its moon. See In your scene.